From miked at dewhirst.com.au Sat Oct 1 00:07:35 2022 From: miked at dewhirst.com.au (Mike Dewhirst) Date: Sat, 1 Oct 2022 14:07:35 +1000 Subject: python developer In-Reply-To: References: Message-ID: On 30/09/2022 3:31 pm, Jan van den Broek wrote: > 2022-09-29, Mike Dewhirst schrieb: >> This is an OpenPGP/MIME signed message (RFC 4880 and 3156) > Why? Good question. Further to Peter's explanation, email is the primary conduit for hackers. At this point in time human education and training is the only defence. The bad guys count on human error because that's what humans are good at. If everyone signed their mail and all mail clients defaulted to expecting signed email from correspondents for whom the public key is known, some of that defence can be delegated to the computer. I'm not expecting this any time soon but it doesn't hurt to get the message out. Most email activists demand end-to-end encryption and obviously signing email is part of that. However, my view is that email privacy, while very important, is an oxymoron. If you need encrypted messages you would never use email. You would meet under a waterfall. So the answer to your question is signed email is easy and if it becomes popular it has potential to defeat hackers. Cheers Mike > [Schnipp] -- Signed email is an absolute defence against phishing. This email has been signed with my private key. If you import my public key you can automatically decrypt my signature and be sure it came from me. Just ask and I'll send it to you. Your email software can handle signing. -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 495 bytes Desc: OpenPGP digital signature URL: From gvanem at yahoo.no Sat Oct 1 11:50:14 2022 From: gvanem at yahoo.no (Gisle Vanem) Date: Sat, 1 Oct 2022 17:50:14 +0200 Subject: Changing 'Scripts/*.exe' References: Message-ID: Hello list. I'm moved my old Python27 installation from f:\ProgramFiler\Python27 ( == 'ProgramFiles') to f:\gv\Python27 and now many 'scripts/*.exe' program fails to start since the old path to 'Python.exe' is wrong. E.g. 'Scripts/pip2.exe' has the path "f:\programfiler\python27\python.exe" hard-coded inside it. Is there a easy way to fix this w/o re-installing this old Python? -- --gv From PythonList at DancesWithMice.info Sat Oct 1 14:16:56 2022 From: PythonList at DancesWithMice.info (dn) Date: Sun, 2 Oct 2022 07:16:56 +1300 Subject: Changing 'Scripts/*.exe' In-Reply-To: References: Message-ID: <183a6d15-6562-964d-535e-b35c8b17a0f9@DancesWithMice.info> On 02/10/2022 04.50, Gisle Vanem via Python-list wrote: > Hello list. > > I'm moved my old Python27 installation from > ? f:\ProgramFiler\Python27? ( == 'ProgramFiles') > to > ? f:\gv\Python27 > > and now many 'scripts/*.exe' program fails > to start since the old path to 'Python.exe' > is wrong. > > E.g. 'Scripts/pip2.exe' has the path > "f:\programfiler\python27\python.exe" hard-coded > inside it. > > Is there a easy way to fix this w/o re-installing this > old Python? Yes, by putting a symbolic-link at the old 'programfiler' location which points to the new 'gv' installation. Regret that not using MS-Windows, can't give exact instruction. Please review: Symbolic link: https://www.computerhope.com/jargon/s/symblink.htm Symbolic Links: https://learn.microsoft.com/en-us/windows/win32/fileio/symbolic-links -- Regards, =dn From balglaas at dds.nl Sat Oct 1 09:11:41 2022 From: balglaas at dds.nl (Jan van den Broek) Date: Sat, 1 Oct 2022 13:11:41 -0000 (UTC) Subject: python developer References: Message-ID: 2022-10-01, Mike Dewhirst schrieb: >So the answer to your question is signed email is easy and if it becomes >popular it has potential to defeat hackers. Yes, but I'm reading this as a usenet-message (comp.lang.python), not as a mail. -- Jan v/d Broek balglaas at dds.nl From bowman at montana.com Sat Oct 1 01:35:55 2022 From: bowman at montana.com (rbowman) Date: Fri, 30 Sep 2022 23:35:55 -0600 Subject: python developer In-Reply-To: References: Message-ID: On 9/30/22 22:07, Mike Dewhirst wrote: > Most email activists demand end-to-end encryption and obviously signing > email is part of that. However, my view is that email privacy, while > very important, is an oxymoron. If you need encrypted messages you would > never use email. You would meet under a waterfall. A friend and I used to encrypt our emails. Anyone decrypting them would find sensitive information from two old farts bitching about the weather. My approach is give them so much data they drown in it. Of course with NSA's Bluffdale facility, that's one hell of a lot. From hjp-python at hjp.at Sat Oct 1 16:19:58 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sat, 1 Oct 2022 22:19:58 +0200 Subject: python developer In-Reply-To: References: Message-ID: <20221001201958.6ss6tivmyp2gatks@hjp.at> On 2022-10-01 13:11:41 -0000, Jan van den Broek wrote: > 2022-10-01, Mike Dewhirst schrieb: > >So the answer to your question is signed email is easy and if it becomes > >popular it has potential to defeat hackers. > > Yes, but I'm reading this as a usenet-message (comp.lang.python), not as > a mail. Well, I'm reading it as a mail :-). There's a gateway between the usenet group and the mailing list. Any message[1] sent to one shows up on the other. Of course any argument for or against signing messages on public mailing lists also is valid on Usenet. Although there is one additional against it on Usenet: There are more newsreaders which still (30 years after RFC 1341[2]) don't implement MIME correctly. hp [1] Not quite: there's a filter to prevent spam and and some other messages from getting to the mailing list. [2] Yeah! Anniversary! (Throws confetti, blows a vuvuzela) -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From miked at dewhirst.com.au Sat Oct 1 22:30:40 2022 From: miked at dewhirst.com.au (Mike Dewhirst) Date: Sun, 02 Oct 2022 13:30:40 +1100 Subject: python developer In-Reply-To: Message-ID: <4Mg7Hm2LVsznVF1@mail.python.org> Ah well! I did not think that far ahead.My apologies for burdening your digest. Should I abandon my quest?M--(Unsigned mail from my phone) -------- Original message --------From: Jan van den Broek Date: 2/10/22 06:58 (GMT+10:00) To: python-list at python.org Subject: Re: python developer 2022-10-01, Mike Dewhirst schrieb:>So the answer to your question is signed email is easy and if it becomes >popular it has potential to defeat hackers.Yes, but I'm reading this as a usenet-message (comp.lang.python), not as a mail.-- Jan v/d Broekbalglaas at dds.nl-- https://mail.python.org/mailman/listinfo/python-list From gvanem at yahoo.no Mon Oct 3 03:48:23 2022 From: gvanem at yahoo.no (Gisle Vanem) Date: Mon, 3 Oct 2022 09:48:23 +0200 Subject: Changing 'Scripts/*.exe' In-Reply-To: <183a6d15-6562-964d-535e-b35c8b17a0f9@DancesWithMice.info> References: <183a6d15-6562-964d-535e-b35c8b17a0f9@DancesWithMice.info> Message-ID: dn wrote: >> E.g. 'Scripts/pip2.exe' has the path >> "f:\programfiler\python27\python.exe" hard-coded >> inside it. >> >> Is there a easy way to fix this w/o re-installing this >> old Python? > > Yes, by putting a symbolic-link at the old 'programfiler' location which > points to the new 'gv' installation. I'm suspicious about sym-links. Instead for 'pip' I just did a 'py -2 get-ip.py' which seems to have fixed it. The newly generated 'f:\gv\Python27\Scripts\pip2.exe' seems to work fine; the list from 'pip2.7.exe list' is correct. -- --gv From PythonList at DancesWithMice.info Mon Oct 3 04:04:45 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 3 Oct 2022 21:04:45 +1300 Subject: Changing 'Scripts/*.exe' In-Reply-To: References: <183a6d15-6562-964d-535e-b35c8b17a0f9@DancesWithMice.info> Message-ID: <9a6087c0-73f6-6067-9d0f-3457270d57e2@DancesWithMice.info> On 03/10/2022 20.48, Gisle Vanem via Python-list wrote: > dn wrote: > >>> E.g. 'Scripts/pip2.exe' has the path >>> "f:\programfiler\python27\python.exe" hard-coded >>> inside it. >>> >>> Is there a easy way to fix this w/o re-installing this >>> old Python? >> >> Yes, by putting a symbolic-link at the old 'programfiler' location which >> points to the new 'gv' installation. > > I'm suspicious about sym-links. OT: I'm sufficiently intrigued to ask "why?" - or are you only talking of the MS-Windows implementation? > Instead for 'pip' I just did a 'py -2 get-ip.py' which seems > to have fixed it. The newly generated 'f:\gv\Python27\Scripts\pip2.exe' > seems to work fine; the list from 'pip2.7.exe list' is correct. As long as things are working again, we're all happy! -- Regards, =dn From orzodk at neomailbox.net Sat Oct 1 16:15:55 2022 From: orzodk at neomailbox.net (orzodk) Date: Sat, 01 Oct 2022 14:15:55 -0600 Subject: python developer In-Reply-To: (Jan van den Broek's message of "Sat, 1 Oct 2022 13:11:41 -0000 (UTC)") References: Message-ID: Jan van den Broek writes: > 2022-10-01, Mike Dewhirst schrieb: > >>So the answer to your question is signed email is easy and if it becomes >>popular it has potential to defeat hackers. > > Yes, but I'm reading this as a usenet-message (comp.lang.python), not as > a mail. You are reading a mirror of the mailing list: "This mailing list is a general discussion list for the Python programming language. Please note that for those who prefer, this list is mirrored to the Usenet newsgroup comp.lang.python" https://mail.python.org/mailman/listinfo/python-list From mmontgomery at levado.to Sun Oct 2 09:39:16 2022 From: mmontgomery at levado.to (Meredith Montgomery) Date: Sun, 02 Oct 2022 10:39:16 -0300 Subject: Changing 'Scripts/*.exe' References: Message-ID: <8635c6bb0b.fsf@levado.to> Gisle Vanem writes: > Hello list. > > I'm moved my old Python27 installation from > f:\ProgramFiler\Python27 ( == 'ProgramFiles') > to > f:\gv\Python27 > > and now many 'scripts/*.exe' program fails > to start since the old path to 'Python.exe' > is wrong. > > E.g. 'Scripts/pip2.exe' has the path > "f:\programfiler\python27\python.exe" hard-coded > inside it. > > Is there a easy way to fix this w/o re-installing this > old Python? Wouldn't it be great if it were portable by default? From mmontgomery at levado.to Mon Oct 3 13:13:29 2022 From: mmontgomery at levado.to (Meredith Montgomery) Date: Mon, 03 Oct 2022 14:13:29 -0300 Subject: on GNU EMACS's python-mode, loading entire buffer References: <86y1v6zzf3.fsf@levado.to> <868rn4zg3m.fsf@levado.to> <86ilm2ncqs.fsf@levado.to> <87wn9mwiby.fsf@gmx.net> Message-ID: <867d1gesp2.fsf@levado.to> Stephen Berman writes: > On Sun, 04 Sep 2022 16:47:07 -0300 Meredith Montgomery > wrote: > >> Meredith Montgomery writes: >> >>> Meredith Montgomery writes: >>> >>> [...] >>> >>>> I would also be interested in a command that restarts the REPL afresh >>>> and reloads my buffer --- sort of like keyboard's [F5] of the IDLE. >>> >>> A partial solution for this is the following procedure. >>> >>> (defun python-revert-and-send-buffer-to-repl () >>> "Revert current buffer and sends it to the Python REPL." >>> (interactive) >>> (revert-buffer "ignore-auto-no" "no-confirm") >>> (python-shell-send-buffer)) >>> >>> We can map this to the F5-key and that improves things. But a restart >>> of the REPL would be the ideal. (Sometimes we really want to start >>> afresh. Sometimes. Most often we don't want that.) >> >> It's not easy to restart the REPL. You can send "quit()" to it and >> invoke run-python again interactively by typing out one command after >> another, but if you write a procedure such as this one below, it doesn't >> work: it gives me the impression that there's a timing issue, that is, >> perhaps the procedure is too fast and something happens before it >> should. >> >> (defun python-save-send-buffer-to-repl () >> (interactive) >> (save-buffer) >> (python-shell-send-string "quit()") >> (run-python) >> (python-shell-send-buffer) >> (python-shell-switch-to-shell)) > > It does seem like a timing issue. This works for me: > > (defun python-save-send-buffer-to-repl () > (interactive) > (save-buffer) > (python-shell-send-string "quit()") > (sit-for 0.1) > (run-python) > (python-shell-send-buffer) > (python-shell-switch-to-shell)) > > But if I decrease the wait to 0.05 it doesn't work. Interesting. I can't reproduce this at all. No matter how long I sit, I always get a similar ``crash''. Here's what happens for me with your procedure, sitting for even 5 seconds. I'm adding a 5-second delay after quitting and after running the REPL. --8<---------------cut here---------------start------------->8--- (defun python-save-send-buffer-to-repl () "Save current buffer and sends it to the Python REPL." (interactive) (save-buffer) (python-shell-send-string "quit()") (sit-for 5) (run-python) (sit-for 5) (python-shell-send-buffer) (python-shell-switch-to-shell)) --8<---------------cut here---------------end--------------->8--- When the REPL comes up, it looks fine. When I try to see if a hello-procedure was defined, I get the following: --8<---------------cut here---------------start------------->8--- >>> Process Python finished Python 3.10.6 (tags/v3.10.6:9c7b4bd, Aug 1 2022, 21:53:49) [MSC v.1932 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> Traceback (most recent call last): File "", line 1, in File "c:/Users/mer/AppData/Local/Temp/pyoUKuUx", line 1 Python 3.10.6 (tags/v3.10.6:9c7b4bd, Aug 1 2022, 21:53:49) [MSC v.1932 64 bit (AMD64)] on win32 ^ SyntaxError: invalid decimal literal >>> >>> hello Traceback (most recent call last): File "", line 1, in NameError: name 'hello' is not defined. Did you mean: 'help'? >>> --8<---------------cut here---------------end--------------->8--- You see? It seems that the Python's banner is sent to the REPL, somehow. I actually see it being sent sometimes --- I see in the minibuffer that the string ``Python 3.10.6 (tags/v3.10.6:9c7b4bd[...]'' was sent to the REPL. Somehow my GNU EMACS is reading the banner and sending it back to the REPL as if it were code in my file. My file contained just this: --8<---------------cut here---------------start------------->8--- # -*- mode: python; python-indent-offset: 2 -*- def hello(): return 1 --8<---------------cut here---------------end--------------->8--- From balglaas at dds.nl Mon Oct 3 13:54:40 2022 From: balglaas at dds.nl (Jan van den Broek) Date: Mon, 3 Oct 2022 17:54:40 -0000 (UTC) Subject: python developer References: Message-ID: 2022-10-01, orzodk schrieb: > Jan van den Broek writes: > >> 2022-10-01, Mike Dewhirst schrieb: >> >>>So the answer to your question is signed email is easy and if it becomes >>>popular it has potential to defeat hackers. >> >> Yes, but I'm reading this as a usenet-message (comp.lang.python), not as >> a mail. > > You are reading a mirror of the mailing list: I was aware of that. -- Jan v/d Broek balglaas at dds.nl From barry at barrys-emacs.org Mon Oct 3 16:20:11 2022 From: barry at barrys-emacs.org (Barry Scott) Date: Mon, 3 Oct 2022 21:20:11 +0100 Subject: Changing 'Scripts/*.exe' In-Reply-To: References: Message-ID: <2D8E7AE1-FAB9-4B1E-B6E0-38EC7EAFD8DD@barrys-emacs.org> > On 1 Oct 2022, at 16:50, Gisle Vanem via Python-list wrote: > > Hello list. > > I'm moved my old Python27 installation from > f:\ProgramFiler\Python27 ( == 'ProgramFiles') > to > f:\gv\Python27 The design of Windows installed software makes this hard to do without a lot of knowledge about what the installation did. For example there are registry keys that hold information on where python 2.7 is installed and there is other software that will read the registry and expect that information to be correct. I would have backed the old installation, uninstalled and the reinstalled python where you want it to be. > > and now many 'scripts/*.exe' program fails > to start since the old path to 'Python.exe' > is wrong. > > E.g. 'Scripts/pip2.exe' has the path > "f:\programfiler\python27\python.exe" hard-coded > inside it. > > Is there a easy way to fix this w/o re-installing this > old Python? The advice you have had will get you someway to fixing the breakage. But do not be surprised if more things break as you try different things out. As I say I would have backed up the files, uninstall and reinstall then put back from backup any files that are not installable anymore. Why did you move the files from where they where installed and working? Barry > > -- > --gv > -- > https://mail.python.org/mailman/listinfo/python-list > From mmontgomery at levado.to Mon Oct 3 21:10:08 2022 From: mmontgomery at levado.to (Meredith Montgomery) Date: Mon, 03 Oct 2022 22:10:08 -0300 Subject: Changing 'Scripts/*.exe' References: <8635c6bb0b.fsf@levado.to> Message-ID: <86zgeccs27.fsf@levado.to> ram at zedat.fu-berlin.de (Stefan Ram) writes: > Meredith Montgomery writes: >>Wouldn't it be great if it were portable by default? > > I think under Windows there is a division of software > suggested by Microsoft, a division of software into > executable code and data (data may change in time). > > The executable code is supposed to rest under > "C:\Program Files" the contents of which cannot be > modified by user processes easily. Program configuration > can be stored below "AppData" in the user directory. > It is supposed to be more secure when executable code > cannot be modified easily by user processes. > > So far, Python has decided to ignore this and install > everything under AppData as I understand it. So one > gets neither the security of "Program Files" nor the > possibility to move it to another directory easily. Interesting. I like portable things. You copy from one place to another and it just runs. As it should. Things should be simple. From PythonList at DancesWithMice.info Mon Oct 3 21:55:36 2022 From: PythonList at DancesWithMice.info (dn) Date: Tue, 4 Oct 2022 14:55:36 +1300 Subject: Changing 'Scripts/*.exe' In-Reply-To: <86zgeccs27.fsf@levado.to> References: <8635c6bb0b.fsf@levado.to> <86zgeccs27.fsf@levado.to> Message-ID: <713d801d-9145-2d8c-eed9-db9221997996@DancesWithMice.info> On 04/10/2022 14.10, Meredith Montgomery wrote: > ram at zedat.fu-berlin.de (Stefan Ram) writes: > >> Meredith Montgomery writes: >>> Wouldn't it be great if it were portable by default? >> >> I think under Windows there is a division of software >> suggested by Microsoft, a division of software into >> executable code and data (data may change in time). >> >> The executable code is supposed to rest under >> "C:\Program Files" the contents of which cannot be >> modified by user processes easily. Program configuration >> can be stored below "AppData" in the user directory. >> It is supposed to be more secure when executable code >> cannot be modified easily by user processes. >> >> So far, Python has decided to ignore this and install >> everything under AppData as I understand it. So one >> gets neither the security of "Program Files" nor the >> possibility to move it to another directory easily. > > Interesting. I like portable things. You copy from one place to At which point we mention that this is exactly how Linux works. A 'zen' of Linux applications and utilities has always been: "do one thing, and do it well". Then directory/file access controls aim to keep users in 'userland' and away from 'system', and for folk who want more there are security features such as apparmor which limit the types of usage of files (as well as resisting external threats). Extending this a little further: such philosophy enables Linux users to more-easily install (and run) multiple versions of Python*, Firefox, Chromium, etc, without resorting to containers or VMs. * eg v2 and v3 installed concurrently, to possibly suit OP > another and it just runs. As it should. Things should be simple. +1 -- Regards, =dn From 2QdxY4RzWzUUiLuE at potatochowder.com Tue Oct 4 05:49:25 2022 From: 2QdxY4RzWzUUiLuE at potatochowder.com (2QdxY4RzWzUUiLuE at potatochowder.com) Date: Tue, 4 Oct 2022 05:49:25 -0400 Subject: Changing 'Scripts/*.exe' In-Reply-To: <713d801d-9145-2d8c-eed9-db9221997996@DancesWithMice.info> References: <8635c6bb0b.fsf@levado.to> <86zgeccs27.fsf@levado.to> <713d801d-9145-2d8c-eed9-db9221997996@DancesWithMice.info> Message-ID: On 2022-10-04 at 14:55:36 +1300, dn wrote: > On 04/10/2022 14.10, Meredith Montgomery wrote: > > ram at zedat.fu-berlin.de (Stefan Ram) writes: > > > >> Meredith Montgomery writes: > >>> Wouldn't it be great if it were portable by default? > >> > >> I think under Windows there is a division of software > >> suggested by Microsoft, a division of software into > >> executable code and data (data may change in time). > >> > >> The executable code is supposed to rest under > >> "C:\Program Files" the contents of which cannot be > >> modified by user processes easily. Program configuration > >> can be stored below "AppData" in the user directory. > >> It is supposed to be more secure when executable code > >> cannot be modified easily by user processes. > >> > >> So far, Python has decided to ignore this and install > >> everything under AppData as I understand it. So one > >> gets neither the security of "Program Files" nor the > >> possibility to move it to another directory easily. > > > > Interesting. I like portable things. You copy from one place to ^ Copy what? That's the crux of it. On vintage (1980s? 1990s? way before OS X, anyway) Mac OS, I could copy an alias (Mac's version of a symbolic link) to a floppy disk, walk (IOW, "transfer via sneaker net") that alias to another Mac on the network, and open *the original file* from that other Mac. (I could even move the file to another folder on the original Mac, but that didn't mean much, because those old file systems were entirely flat (directories and folders were an illusion maintained by the Finder).) Permissions? We don't need no stinkin' permissions! ;-) > > another and it just runs. As it should. Things should be simple. > > +1 I like simple, portable things, too. But this kind of simplicity (applications looking in known locations for certain files) and this kind of portability (allowing users to move those files) are at oods. And that's before we consider security. Also, [almost] by definition, Python virtual environments really blur the lines between user, system, public, private, programs, and data. From andreas.0815.qwertz at gmail.com Tue Oct 4 05:05:42 2022 From: andreas.0815.qwertz at gmail.com (Andreas Ames) Date: Tue, 4 Oct 2022 11:05:42 +0200 Subject: Performance issue with CPython 3.10 + Cython Message-ID: Hi all, I am wrapping an embedded application (, which does not use any dynamic memory management,) using Cython to call it from CPython. The wrapped application uses a cyclic executive, i.e. everything is done in the input-logic-output design, typical for some real-time related domains. Consequentially, every application cycle executes more or less the very same code. As I am still in a prototyping stadium, the wrapped process is completely CPU-bound, i.e. except of some logging output there is no I/O whatsoever. During one second of "application time", I am doing exactly 120 calls into the application through three Cython-wrapped API functions. The application uses some platform-dependent APIs, which I have also wrapped with Cython, so that there are numerous callbacks into the Python realm per call into the application. What I am observing now, is that the performance per "application second" decreases (remember: executing code that does the same thing on every cycle) and extending the number of loop iterations does not seem to cause any bound to this decrease. In the log ouput below, you can see the GC counts, which look innocent to me. The "real time" is measured using "time.time()". The "top" utility does not suggest any memory leak either. I am developing on WSL2, but I have checked that this performance effect also happens on physical machines. Right now, I am staring at "kcachegrind", but I have no idea, how to determine time series for the performance of functions (I am not looking for those functions, which need the most time, but for those, which consume more and more execution time). One more thing to look for could be memory fragmentation, but before that I would like to ask the experts here for their ideas and experiences and/or for tools, which could help to find the culprit. 2022-10-04 10:40:50|INFO |__main__ |Execution loop 0 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.06862711906433105 seconds real time. > 2022-10-04 10:40:51|INFO |__main__ |Execution loop 100 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.08224177360534668 seconds real time. > 2022-10-04 10:40:52|INFO |__main__ |Execution loop 200 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.08225250244140625 seconds real time. > 2022-10-04 10:40:53|INFO |__main__ |Execution loop 300 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.10176873207092285 seconds real time. > 2022-10-04 10:40:54|INFO |__main__ |Execution loop 400 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.10900592803955078 seconds real time. > 2022-10-04 10:40:55|INFO |__main__ |Execution loop 500 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.12233948707580566 seconds real time. > 2022-10-04 10:40:56|INFO |__main__ |Execution loop 600 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.14058256149291992 seconds real time. > 2022-10-04 10:40:58|INFO |__main__ |Execution loop 700 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.14777183532714844 seconds real time. > 2022-10-04 10:40:59|INFO |__main__ |Execution loop 800 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.15729451179504395 seconds real time. > 2022-10-04 10:41:01|INFO |__main__ |Execution loop 900 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.17365813255310059 seconds real time. > 2022-10-04 10:41:03|INFO |__main__ |Execution loop 1000 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.17772984504699707 seconds real time. > 2022-10-04 10:41:05|INFO |__main__ |Execution loop 1100 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.1955263614654541 seconds real time. > 2022-10-04 10:41:07|INFO |__main__ |Execution loop 1200 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.20046710968017578 seconds real time. > 2022-10-04 10:41:09|INFO |__main__ |Execution loop 1300 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.22513842582702637 seconds real time. > 2022-10-04 10:41:11|INFO |__main__ |Execution loop 1400 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.23578548431396484 seconds real time. > 2022-10-04 10:41:13|INFO |__main__ |Execution loop 1500 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.24581527709960938 seconds real time. > 2022-10-04 10:41:16|INFO |__main__ |Execution loop 1600 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.2541334629058838 seconds real time. > 2022-10-04 10:41:19|INFO |__main__ |Execution loop 1700 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.26812195777893066 seconds real time. > 2022-10-04 10:41:21|INFO |__main__ |Execution loop 1800 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.28777456283569336 seconds real time. > 2022-10-04 10:41:24|INFO |__main__ |Execution loop 1900 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.3005337715148926 seconds real time. > 2022-10-04 10:41:28|INFO |__main__ |Execution loop 2000 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.30992960929870605 seconds real time. > 2022-10-04 10:41:31|INFO |__main__ |Execution loop 2100 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.32058119773864746 seconds real time. > 2022-10-04 10:41:34|INFO |__main__ |Execution loop 2200 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.33020949363708496 seconds real time. > 2022-10-04 10:41:37|INFO |__main__ |Execution loop 2300 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.34426307678222656 seconds real time. > 2022-10-04 10:41:41|INFO |__main__ |Execution loop 2400 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.35851263999938965 seconds real time. > 2022-10-04 10:41:45|INFO |__main__ |Execution loop 2500 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.3664553165435791 seconds real time. > 2022-10-04 10:41:48|INFO |__main__ |Execution loop 2600 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.3767662048339844 seconds real time. > 2022-10-04 10:41:52|INFO |__main__ |Execution loop 2700 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.39760732650756836 seconds real time. > 2022-10-04 10:41:56|INFO |__main__ |Execution loop 2800 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.42221736907958984 seconds real time. > 2022-10-04 10:42:01|INFO |__main__ |Execution loop 2900 done. GC > counts = (381, 9, 3); 1 second of application time corresponds to > 0.4237234592437744 seconds real time. Thanks in advance, Andreas From greg.ewing at canterbury.ac.nz Tue Oct 4 18:27:45 2022 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Wed, 5 Oct 2022 11:27:45 +1300 Subject: Changing 'Scripts/*.exe' In-Reply-To: References: <8635c6bb0b.fsf@levado.to> <86zgeccs27.fsf@levado.to> <713d801d-9145-2d8c-eed9-db9221997996@DancesWithMice.info> Message-ID: On 4/10/22 10:49 pm, 2QdxY4RzWzUUiLuE at potatochowder.com wrote: > (I could even move > the file to another folder on the original Mac, but that didn't mean > much, because those old file systems were entirely flat (directories and > folders were an illusion maintained by the Finder) That was only true in the very early days. A proper hierarchical file system was available as soon as hard disks became common (around the Mac II era I think?) However, internally each file on a volume was identified by a File ID (something a bit like an inode number) and that was stored in the alias and used as the first means of finding the file. There was also a pathname stored in the alias, but that was only used as a backup in case the file couldn't be found using the File ID. So a Mac alias was in some ways more powerful than a symlink, but in other ways less -- e.g. there was no equivalent to a relative symlink. Also aliases are more like a Windows shortcut in that they aren't resolved automatically in the kernel -- programs need to be aware of them and take explicit action to resolve them. Things are even more confusing in MacOSX, which has both aliases *and* symlinks, they behave differently, and the Finder doesn't tell you which you're looking at. :-( -- Greg From david at protonic.nl Thu Oct 6 10:10:06 2022 From: david at protonic.nl (David Jander) Date: Thu, 6 Oct 2022 16:10:06 +0200 Subject: Pythonic way to run the asyncio loop forever in python 3.10 Message-ID: <20221006161006.0a0a9a00@erd992> Hello, It is highly likely this has been discussed before, but I haven't been able to find the answer to my question, so if anyone knows, please send me to the right place. Thanks. I am migrating a lot of python software to 3.10, which has deprecated calling asyncio.get_event_loop() from outside the loop. While doing so, I have bumped against some common (I think) use-cases which seem to have no elegant solution anymore. At least I can't find one that seems "pythonic" or "correct". Problem: Before 3.10, asyncio.get_event_loop() was a convenient way to manage the loop singleton. In single-threaded applications, normally you want only a single instance of an event loop. The easiest way to make sure there was only one loop ever created, was to call asyncio.get_event_loop(). Since the only place this is crucially important to get right is _outside_ of the loop (because once inside the loop all damage is done already anyway), deprecating this use-case basically seems to destroy the usefulness of that method, and also many other methods of loop, like loop.run_forever() and loop.run_until_complete(). Example: Suppose an application that does a bunch of (blocking and CPU intensive) initialization, while also setting up event handlers, that may call things like loop.add_reader() or loop.call_soon() in many different places. Then, after all initialization is done, loop.run_forever() is called to get the application running. Notice, that there may not even be a single coroutine involved. Someone else asked something similar here: https://stackoverflow.com/questions/65684730/what-is-the-pythonic-way-of-running-an-asyncio-event-loop-forever Unfortunately all proposed answers look like dirty hacks. In concrete, how do I do this nicely? async def main(): loop = asyncio.get_running_loop() ... loop.add_reader(...) ... loop.call_later(...) ... ... etc... # HACK: Now wait forever to keep the loop running await asyncio.Future() if __name__ == "__main__": asyncio.run(main()) It can't be seriously the intention that people do these kind of things, right? This example application might not even use coroutines at all, and be entirely event driven. Yet an initial coroutine is now required. No way to run the loop without one. The worst thing is that all the initialization and blocking code cannot be easily mixed with loop setup anymore, because loop setup before starting the loop has essentially been killed by python developers. Please correct me if I am wrong about any of this. What am I missing here? Unfortunately the world is now seemingly filled with horrible and sometimes broken workarounds for this change introduced in 3.10: https://github.com/aio-libs/aiohttp/blob/master/aiohttp/web.py#L434 https://github.com/tornadoweb/tornado/blob/master/demos/tcpecho/server.py#L36 etc... Where is the discussion about this, and where are the proposed solutions? Python 3.11 seems to mitigate this problem by introducing the asyncio.Runner() context-manager. But for the time being for 3.10, I see no good solution. Best regards, -- David Jander From PythonList at DancesWithMice.info Fri Oct 7 00:47:29 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 7 Oct 2022 17:47:29 +1300 Subject: From NZPUG: Smart Iterator Challenge Message-ID: <0a27bb55-43fe-3200-5103-bc62421b8527@DancesWithMice.info> A week-by-week Challenge series. A new venture by the Auckland Branch of the New Zealand Python Users' Group (AuckPUG) Challenge-week 2: Modular programming - starts today Please note: all times are NZDT, ie UTC+13 All welcome! - will suit Python-Apprentices ready to move-on from 'the basics' and Python-Journeymen - will welcome participation and coaching-contributions from Python-Masters, with a special Challenge to be issued at that level Kiwi accent optional (most people are no-good at it anyway). With special thanks to our own Leam Hall, for feedback and advice - that said, all errors and omissions are mine. To avoid OT traffic on-list, please find all details, and file any follow-up questions through the Meetup-site: https://www.meetup.com/nzpug-auckland/events/288813698/ (or email myself directly). Are you up for a challenge? Regards =dn (for Pete and DJ) From dioumacorfaye at gmail.com Fri Oct 7 06:17:45 2022 From: dioumacorfaye at gmail.com (Dioumacor FAYE) Date: Fri, 7 Oct 2022 10:17:45 +0000 Subject: How to create forecast lead time with python? Message-ID: Hello, I wanted to create on different days the deadline forecast files (2, 3, 4, and 5 deadlines). The file is in NetCDF format. The objective is to see later on these different forecast deadlines which one gives the best score. If anyone can help me to do? -- Bien ? vous, --------------------- ------------------ ----------------- -------------------- ----------------- Dioumacor FAYE doctorant au LPAOSF/ESP/UCAD/BP 5085 Dakar-Fann, S?n?gal. Tel labo: (00221) 33 825 93 64 Email: d.faye20171634 at zig.univ.sn Tel: +221773475098 +221783484308 Physicien en herbe Pseudo Skype: dioumacorfaye From jorge.conforte at inpe.br Fri Oct 7 07:53:01 2022 From: jorge.conforte at inpe.br (Jorge Conrado Conforte) Date: Fri, 7 Oct 2022 08:53:01 -0300 (BRT) Subject: Gdal Message-ID: <1180000930.9292306.1665143581642.JavaMail.zimbra@inpe.br> Hi, I installed GDAL using the pip command and conda. But, I did: import gdal and I had: Traceback (most recent call last): File "", line 1, in ModuleNotFoundError: No module named 'gdal' I need gdal to remap some data. Please, help me Conrado From dioumacorfaye at gmail.com Fri Oct 7 09:01:15 2022 From: dioumacorfaye at gmail.com (Dioumacor FAYE) Date: Fri, 7 Oct 2022 13:01:15 +0000 Subject: Gdal In-Reply-To: <1180000930.9292306.1665143581642.JavaMail.zimbra@inpe.br> References: <1180000930.9292306.1665143581642.JavaMail.zimbra@inpe.br> Message-ID: If you are working on ubuntu, you can use this command. conda create --name pygdal conda activate pygdal conda install -c conda-forge gdal If installation completes import it from: from osgeo import gdal Le ven. 7 oct. 2022 ? 12:01, "Jorge Conrado Conforte" < jorge.conforte at inpe.br> a ?crit : > > > Hi, > > > > > I installed GDAL using the pip command and conda. But, I did: > > import gdal and I had: > > Traceback (most recent call last): > File "", line 1, in > ModuleNotFoundError: No module named 'gdal' > > > > > > I need gdal to remap some data. > > Please, help me > > > > > Conrado > -- > https://mail.python.org/mailman/listinfo/python-list > -- Bien ? vous, --------------------- ------------------ ----------------- -------------------- ----------------- Dioumacor FAYE doctorant au LPAOSF/ESP/UCAD/BP 5085 Dakar-Fann, S?n?gal. Tel labo: (00221) 33 825 93 64 Email: d.faye20171634 at zig.univ.sn Tel: +221773475098 +221783484308 Physicien en herbe Pseudo Skype: dioumacorfaye From andreas.0815.qwertz at gmail.com Fri Oct 7 10:39:00 2022 From: andreas.0815.qwertz at gmail.com (Andreas Ames) Date: Fri, 7 Oct 2022 16:39:00 +0200 Subject: Performance issue with CPython 3.10 + Cython In-Reply-To: References: Message-ID: Answering to myself, just for the records: 1. The culprit was me. As lazy as I am, I have used f-strings all over the place in calls to `logging.logger.debug()` and friends, evaluating all arguments regardless of whether the logger was enabled or not. Replacing these f-strings by regular printf-like format strings solved the issue. Now the application bowls happily along, consistently below 0.02 seconds per second application time. 2. Valgrind + callgrind is an awesome toolchain to spot performance issues, even on VMs. Am Di., 4. Okt. 2022 um 11:05 Uhr schrieb Andreas Ames < andreas.0815.qwertz at gmail.com>: > Hi all, > > I am wrapping an embedded application (, which does not use any dynamic > memory management,) using Cython to call it from CPython. The wrapped > application uses a cyclic executive, i.e. everything is done in the > input-logic-output design, typical for some real-time related domains. > Consequentially, every application cycle executes more or less the very > same code. As I am still in a prototyping stadium, the wrapped process is > completely CPU-bound, i.e. except of some logging output there is no I/O > whatsoever. > > During one second of "application time", I am doing exactly 120 calls into > the application through three Cython-wrapped API functions. The > application uses some platform-dependent APIs, which I have also wrapped > with Cython, so that there are numerous callbacks into the Python realm per > call into the application. What I am observing now, is that the performance > per "application second" decreases (remember: executing code that does the > same thing on every cycle) and extending the number of loop iterations does > not seem to cause any bound to this decrease. In the log ouput below, you > can see the GC counts, which look innocent to me. The "real time" is > measured using "time.time()". The "top" utility does not suggest any memory > leak either. I am developing on WSL2, but I have checked that this > performance effect also happens on physical machines. Right now, I am > staring at "kcachegrind", but I have no idea, how to determine time series > for the performance of functions (I am not looking for those functions, > which need the most time, but for those, which consume more and more > execution time). > > One more thing to look for could be memory fragmentation, but before that > I would like to ask the experts here for their ideas and experiences and/or > for tools, which could help to find the culprit. > > 2022-10-04 10:40:50|INFO |__main__ |Execution loop 0 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.06862711906433105 seconds real time. >> 2022-10-04 10:40:51|INFO |__main__ |Execution loop 100 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.08224177360534668 seconds real time. >> 2022-10-04 10:40:52|INFO |__main__ |Execution loop 200 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.08225250244140625 seconds real time. >> 2022-10-04 10:40:53|INFO |__main__ |Execution loop 300 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.10176873207092285 seconds real time. >> 2022-10-04 10:40:54|INFO |__main__ |Execution loop 400 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.10900592803955078 seconds real time. >> 2022-10-04 10:40:55|INFO |__main__ |Execution loop 500 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.12233948707580566 seconds real time. >> 2022-10-04 10:40:56|INFO |__main__ |Execution loop 600 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.14058256149291992 seconds real time. >> 2022-10-04 10:40:58|INFO |__main__ |Execution loop 700 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.14777183532714844 seconds real time. >> 2022-10-04 10:40:59|INFO |__main__ |Execution loop 800 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.15729451179504395 seconds real time. >> 2022-10-04 10:41:01|INFO |__main__ |Execution loop 900 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.17365813255310059 seconds real time. >> 2022-10-04 10:41:03|INFO |__main__ |Execution loop 1000 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.17772984504699707 seconds real time. >> 2022-10-04 10:41:05|INFO |__main__ |Execution loop 1100 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.1955263614654541 seconds real time. >> 2022-10-04 10:41:07|INFO |__main__ |Execution loop 1200 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.20046710968017578 seconds real time. >> 2022-10-04 10:41:09|INFO |__main__ |Execution loop 1300 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.22513842582702637 seconds real time. >> 2022-10-04 10:41:11|INFO |__main__ |Execution loop 1400 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.23578548431396484 seconds real time. >> 2022-10-04 10:41:13|INFO |__main__ |Execution loop 1500 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.24581527709960938 seconds real time. >> 2022-10-04 10:41:16|INFO |__main__ |Execution loop 1600 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.2541334629058838 seconds real time. >> 2022-10-04 10:41:19|INFO |__main__ |Execution loop 1700 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.26812195777893066 seconds real time. >> 2022-10-04 10:41:21|INFO |__main__ |Execution loop 1800 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.28777456283569336 seconds real time. >> 2022-10-04 10:41:24|INFO |__main__ |Execution loop 1900 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.3005337715148926 seconds real time. >> 2022-10-04 10:41:28|INFO |__main__ |Execution loop 2000 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.30992960929870605 seconds real time. >> 2022-10-04 10:41:31|INFO |__main__ |Execution loop 2100 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.32058119773864746 seconds real time. >> 2022-10-04 10:41:34|INFO |__main__ |Execution loop 2200 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.33020949363708496 seconds real time. >> 2022-10-04 10:41:37|INFO |__main__ |Execution loop 2300 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.34426307678222656 seconds real time. >> 2022-10-04 10:41:41|INFO |__main__ |Execution loop 2400 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.35851263999938965 seconds real time. >> 2022-10-04 10:41:45|INFO |__main__ |Execution loop 2500 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.3664553165435791 seconds real time. >> 2022-10-04 10:41:48|INFO |__main__ |Execution loop 2600 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.3767662048339844 seconds real time. >> 2022-10-04 10:41:52|INFO |__main__ |Execution loop 2700 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.39760732650756836 seconds real time. >> 2022-10-04 10:41:56|INFO |__main__ |Execution loop 2800 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.42221736907958984 seconds real time. >> 2022-10-04 10:42:01|INFO |__main__ |Execution loop 2900 done. GC >> counts = (381, 9, 3); 1 second of application time corresponds to >> 0.4237234592437744 seconds real time. > > > Thanks in advance, > > Andreas > > From skip.montanaro at gmail.com Fri Oct 7 11:45:26 2022 From: skip.montanaro at gmail.com (Skip Montanaro) Date: Fri, 7 Oct 2022 10:45:26 -0500 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames wrote: > 1. The culprit was me. As lazy as I am, I have used f-strings all over the > place in calls to `logging.logger.debug()` and friends, evaluating all > arguments regardless of whether the logger was enabled or not. > I thought there was some discussion about whether and how to efficiently admit f-strings to the logging package. I'm guessing that's not gone anywhere (yet). Skip From skip.montanaro at gmail.com Fri Oct 7 12:03:08 2022 From: skip.montanaro at gmail.com (Skip Montanaro) Date: Fri, 7 Oct 2022 11:03:08 -0500 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: Dang autocorrect. Subject first word was supposed to be "f-strings" not "ref-strings." Sorry about that. S On Fri, Oct 7, 2022, 10:45 AM Skip Montanaro wrote: > > > On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames > wrote: > >> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >> place in calls to `logging.logger.debug()` and friends, evaluating all >> arguments regardless of whether the logger was enabled or not. >> > > I thought there was some discussion about whether and how to efficiently > admit f-strings to the logging package. I'm guessing that's not gone > anywhere (yet). > > Skip > From barry at barrys-emacs.org Fri Oct 7 13:04:33 2022 From: barry at barrys-emacs.org (Barry) Date: Fri, 7 Oct 2022 18:04:33 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: > On 7 Oct 2022, at 16:48, Skip Montanaro wrote: > > ?On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames > wrote: > >> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >> place in calls to `logging.logger.debug()` and friends, evaluating all >> arguments regardless of whether the logger was enabled or not. >> > > I thought there was some discussion about whether and how to efficiently > admit f-strings to the logging package. I'm guessing that's not gone > anywhere (yet). That cannot be done as the f-string is computed before the log call. Maybe you are thinking of the lazy expression idea for this. That idea seems to have got no where as its not clear how to implement it without performance issues. Barry > > Skip > -- > https://mail.python.org/mailman/listinfo/python-list > From python at mrabarnett.plus.com Fri Oct 7 13:10:33 2022 From: python at mrabarnett.plus.com (MRAB) Date: Fri, 7 Oct 2022 18:10:33 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: On 2022-10-07 16:45, Skip Montanaro wrote: > On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames > wrote: > >> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >> place in calls to `logging.logger.debug()` and friends, evaluating all >> arguments regardless of whether the logger was enabled or not. >> > > I thought there was some discussion about whether and how to efficiently > admit f-strings to the logging package. I'm guessing that's not gone > anywhere (yet). > Letting you pass in a callable to call might help because that you could use lambda. From barry at barrys-emacs.org Fri Oct 7 13:28:06 2022 From: barry at barrys-emacs.org (Barry) Date: Fri, 7 Oct 2022 18:28:06 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: > On 7 Oct 2022, at 18:16, MRAB wrote: > > ?On 2022-10-07 16:45, Skip Montanaro wrote: >>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames >>> wrote: >>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >>> place in calls to `logging.logger.debug()` and friends, evaluating all >>> arguments regardless of whether the logger was enabled or not. >>> >> I thought there was some discussion about whether and how to efficiently >> admit f-strings to the logging package. I'm guessing that's not gone >> anywhere (yet). > Letting you pass in a callable to call might help because that you could use lambda. Yep, that?s the obvious way to avoid expensive log data generation. Would need logging module to support that use case. Barry > -- > https://mail.python.org/mailman/listinfo/python-list > From gweatherby at uchc.edu Fri Oct 7 13:55:13 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Fri, 7 Oct 2022 17:55:13 +0000 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: The obvious way to avoid log generation is: if logger.isEnableFor(logging.DEBUG): logger.debug( expensive processing ) Of course, having logging alter program flow could lead to hard to debug bugs. From: Python-list on behalf of Barry Date: Friday, October 7, 2022 at 1:30 PM To: MRAB Cc: python-list at python.org Subject: Re: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > On 7 Oct 2022, at 18:16, MRAB wrote: > > ?On 2022-10-07 16:45, Skip Montanaro wrote: >>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames >>> wrote: >>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >>> place in calls to `logging.logger.debug()` and friends, evaluating all >>> arguments regardless of whether the logger was enabled or not. >>> >> I thought there was some discussion about whether and how to efficiently >> admit f-strings to the logging package. I'm guessing that's not gone >> anywhere (yet). > Letting you pass in a callable to call might help because that you could use lambda. Yep, that?s the obvious way to avoid expensive log data generation. Would need logging module to support that use case. Barry > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ > -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ From barry at barrys-emacs.org Fri Oct 7 17:15:17 2022 From: barry at barrys-emacs.org (Barry) Date: Fri, 7 Oct 2022 22:15:17 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) Message-ID: > On 7 Oct 2022, at 19:09, Weatherby,Gerard wrote: > ?The obvious way to avoid log generation is: > > if logger.isEnableFor(logging.DEBUG): > logger.debug( expensive processing ) > > > Of course, having logging alter program flow could lead to hard to debug bugs. Altered flow is less of an issue the the verbosity of the above. We discussed ways to improve this pattern a few years ago. That lead to no changes. What I have used is a class that defines __bool__ to report if logging is enabled and __call__ to log. Then you can do this: log_debug = logger_from(DEBUG) log_debug and log_debug(?expensive %s? % (complex(),)) Barry > > From: Python-list on behalf of Barry > Date: Friday, October 7, 2022 at 1:30 PM > To: MRAB > Cc: python-list at python.org > Subject: Re: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) > *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > >> On 7 Oct 2022, at 18:16, MRAB wrote: >> >> ?On 2022-10-07 16:45, Skip Montanaro wrote: >>>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames >>>> wrote: >>>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >>>> place in calls to `logging.logger.debug()` and friends, evaluating all >>>> arguments regardless of whether the logger was enabled or not. >>> I thought there was some discussion about whether and how to efficiently >>> admit f-strings to the logging package. I'm guessing that's not gone >>> anywhere (yet). >> Letting you pass in a callable to call might help because that you could use lambda. > > Yep, that?s the obvious way to avoid expensive log data generation. > Would need logging module to support that use case. > > Barry > >> -- >> https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ > > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ > -- > https://mail.python.org/mailman/listinfo/python-list From c.buhtz at posteo.jp Fri Oct 7 04:38:40 2022 From: c.buhtz at posteo.jp (c.buhtz at posteo.jp) Date: Fri, 7 Oct 2022 08:38:40 +0000 Subject: Debugging automatic quotation in subprocess.Popen() Message-ID: <4MkMCn3lHnz9rxX@submission02.posteo.de> Hello, I need to improve my understanding about how subprocess.Popen() does quote arguments. I have special case here. Simple example: Popen(['ls', '-l']) results on a shell in "ls -l" without quotation. Quotes are added if they are needed: Popen(['ls', 'folder with blank']) results on a shell in "ls 'folder with blank'". Am I right so far with the basics? Is there a way to be sure and to debug how Popen() give it to the shell? From loris.bennett at fu-berlin.de Fri Oct 7 09:00:13 2022 From: loris.bennett at fu-berlin.de (Loris Bennett) Date: Fri, 07 Oct 2022 15:00:13 +0200 Subject: Gdal References: <1180000930.9292306.1665143581642.JavaMail.zimbra@inpe.br> Message-ID: <874jwfdc0y.fsf@hornfels.zedat.fu-berlin.de> Hi Conrado, "\"Jorge Conrado Conforte\"" writes: > Hi, > > > > > I installed GDAL using the pip command and conda. But, I did: > > import gdal and I had: Depending on your GDAL version, you might find you have to do from osgeo import gdal See https://gdal.org/api/python_bindings.html#tutorials Cheers, Loris > Traceback (most recent call last): > File "", line 1, in > ModuleNotFoundError: No module named 'gdal' > > > > > > I need gdal to remap some data. > > Please, help me > > > > > Conrado -- This signature is currently under construction. From robinvdveer at gmail.com Fri Oct 7 14:16:02 2022 From: robinvdveer at gmail.com (Robin van der veer) Date: Fri, 7 Oct 2022 20:16:02 +0200 Subject: Will "hello" always be printed? Message-ID: If I have two processes communicating through a JoinableQueue, and I do the following: process 1: queue.put(1) #unfished tasks = 1 queue.join() #block until unfished tasks = 0 print('hello')[/python] process 2: queue.get() queue.task_done() #unfished tasks = 0 queue.put(1) #unfinished tasks 1[/python] the unfished tasks refers to what is written in the documentation ( https://docs.python.org/3/library/multiprocessing.html#multiprocessing.JoinableQueue.join ) will 'hello' always be printed? Or is there a chance that the put in process 2 executes before process 1 noticed that it should unblock? It seems that the whole point of join() is that 'hello' should always be printed, but I just want to make sure that I understand it correctly. From jules at op59.net Fri Oct 7 16:12:42 2022 From: jules at op59.net (Julian Smith) Date: Fri, 7 Oct 2022 21:12:42 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: <20221007211242.23ede455.jules@op59.net> On Fri, 7 Oct 2022 18:28:06 +0100 Barry wrote: > > On 7 Oct 2022, at 18:16, MRAB wrote: > > > > ?On 2022-10-07 16:45, Skip Montanaro wrote: > >>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames > >>> wrote: > >>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the > >>> place in calls to `logging.logger.debug()` and friends, evaluating all > >>> arguments regardless of whether the logger was enabled or not. > >>> > >> I thought there was some discussion about whether and how to efficiently > >> admit f-strings to the logging package. I'm guessing that's not gone > >> anywhere (yet). > > Letting you pass in a callable to call might help because that you could use lambda. > > Yep, that?s the obvious way to avoid expensive log data generation. > Would need logging module to support that use case. I have some logging code that uses eval() to evaluate expressions using locals and globals in a parent stack frame, together with a parser to find `{...}` items in a string. I guess this constitutes a (basic) runtime implementation of f-strings. As such it can avoid expensive evaluation/parsing when disabled, though it's probably slow when enabled compared to native f-strings. It seems to work quite well in practise, and also allows one to add some extra formatting features. For details see: https://git.ghostscript.com/?p=mupdf.git;a=blob;f=scripts/jlib.py;h=e85e9f2c4;hb=HEAD#l41 - Jules -- http://op59.net From rosuav at gmail.com Fri Oct 7 17:27:57 2022 From: rosuav at gmail.com (Chris Angelico) Date: Sat, 8 Oct 2022 08:27:57 +1100 Subject: Debugging automatic quotation in subprocess.Popen() In-Reply-To: <4MkMCn3lHnz9rxX@submission02.posteo.de> References: <4MkMCn3lHnz9rxX@submission02.posteo.de> Message-ID: On Sat, 8 Oct 2022 at 08:24, wrote: > > Hello, > > I need to improve my understanding about how subprocess.Popen() does > quote arguments. I have special case here. > > Simple example: > Popen(['ls', '-l']) results on a shell in "ls -l" without quotation. > > Quotes are added if they are needed: > Popen(['ls', 'folder with blank']) results on a shell in > "ls 'folder with blank'". > > Am I right so far with the basics? > > Is there a way to be sure and to debug how Popen() give it to the shell? That's kinda looking at it backwards; the shell first splits the command into a list of arguments, and then runs it. Python has a module that is capable of doing similar sorts of work: https://docs.python.org/3/library/shlex.html That may be helpful if you want to give the user something to copy and paste. ChrisA From eryksun at gmail.com Fri Oct 7 17:53:34 2022 From: eryksun at gmail.com (Eryk Sun) Date: Fri, 7 Oct 2022 16:53:34 -0500 Subject: Debugging automatic quotation in subprocess.Popen() In-Reply-To: <4MkMCn3lHnz9rxX@submission02.posteo.de> References: <4MkMCn3lHnz9rxX@submission02.posteo.de> Message-ID: On 10/7/22, c.buhtz at posteo.jp wrote: > > I need to improve my understanding about how subprocess.Popen() does > quote arguments. I have special case here. > > Simple example: > Popen(['ls', '-l']) results on a shell in "ls -l" without quotation. The shell is only used if Popen is instantiated with `shell=True`. The above example does not use the shell. It runs the "ls" executable directly. On POSIX systems, fork() and exec() are called to create the child process. The argument list is passed to exec() and becomes the argv array of the application's main() entry point function. On Windows systems, CreateProcessW() is called to created the child process. It requires a command-line string instead of an argument array. The argument list gets joined into a command-line string via subprocess.list2cmdline(), which is based on the rules that are used by the Windows C runtime library when it parses a command line into the argv array of an application's [w]main() entry point. That said, a Windows application is free to parse its command line however it wants, so listcmdline() is little more than a best guess. On Windows, Popen() may have to be called directly with a command-line string in some cases. From cs at cskk.id.au Fri Oct 7 19:40:10 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Sat, 8 Oct 2022 10:40:10 +1100 Subject: Will "hello" always be printed? In-Reply-To: References: Message-ID: On 07Oct2022 20:16, Robin van der veer wrote: >If I have two processes communicating through a JoinableQueue, and I do the >following: > >process 1: > > queue.put(1) #unfished tasks = 1 > queue.join() #block until unfished tasks = 0 > print('hello')[/python] > >process 2: > > queue.get() > queue.task_done() #unfished tasks = 0 > queue.put(1) #unfinished tasks 1[/python] >the unfished tasks refers to what is written in the documentation ( >https://docs.python.org/3/library/multiprocessing.html#multiprocessing.JoinableQueue.join >) > >will 'hello' always be printed? Or is there a chance that the put in >process 2 executes before process 1 noticed that it should unblock? I had to read this closely. Yes, the second `put(1)` could execute before the `join()` commences (or tests), and the `hello` would be blocked still. >It seems that the whole point of join() is that 'hello' should always be >printed, but I just want to make sure that I understand it correctly. That's the purpose of using `join`, but you need to use it correctly. The "some tasks are not completed" condition which `join` supports doesn't fit what you're doing. So yes, you're correct in your concern. Maybe 2 queues would suit you better? Maybe not if they are common. Maybe some kind of blocking counter, so that you could track task counts? You'd need to make one, but something which allowed: count = queue.put(1) queue.wait_for(count) print('hello') and at the other end: queue.get() queue.task_done() # bumps the counter count2 = queue.put(1) Here, the counter would not be the internal "unfinished tasks" counter but instead a distinct counter which always went up. Probably a pair: tasks submitted by `put` and tasks completed by `task_done`. You could subclass `JoinableQueue` and add implementations of these counters and add a `wait_for(count)` method. This amounts to assigning each "task" a unique id (the counter) and a means to wait for that id. Cheers, Cameron Simpson From python at mrabarnett.plus.com Fri Oct 7 21:01:28 2022 From: python at mrabarnett.plus.com (MRAB) Date: Sat, 8 Oct 2022 02:01:28 +0100 Subject: Will "hello" always be printed? In-Reply-To: References: Message-ID: On 2022-10-08 00:40, Cameron Simpson wrote: > On 07Oct2022 20:16, Robin van der veer wrote: >>If I have two processes communicating through a JoinableQueue, and I do the >>following: >> >>process 1: >> >> queue.put(1) #unfished tasks = 1 >> queue.join() #block until unfished tasks = 0 >> print('hello')[/python] >> >>process 2: >> >> queue.get() >> queue.task_done() #unfished tasks = 0 >> queue.put(1) #unfinished tasks 1[/python] >>the unfished tasks refers to what is written in the documentation ( >>https://docs.python.org/3/library/multiprocessing.html#multiprocessing.JoinableQueue.join >>) >> >>will 'hello' always be printed? Or is there a chance that the put in >>process 2 executes before process 1 noticed that it should unblock? > > I had to read this closely. Yes, the second `put(1)` could execute > before the `join()` commences (or tests), and the `hello` would be > blocked still. > >>It seems that the whole point of join() is that 'hello' should always be >>printed, but I just want to make sure that I understand it correctly. > > That's the purpose of using `join`, but you need to use it correctly. > The "some tasks are not completed" condition which `join` supports > doesn't fit what you're doing. > > So yes, you're correct in your concern. > > Maybe 2 queues would suit you better? Maybe not if they are common. > I would go with 2 queues: 1 for input and 1 for output. The outputted item would be either a result or an indication of an error. [snip] From axy at declassed.art Fri Oct 7 23:32:24 2022 From: axy at declassed.art (Axy) Date: Sat, 8 Oct 2022 04:32:24 +0100 Subject: for -- else: what was the motivation? Message-ID: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Hi there, this is rather a philosophical question, but I assume I miss something. I don't remember I ever used else clause for years I was with python and my expectation was it executed only if the the main body was never run. Ha-ha! I was caught by this mental trap. So, seriously, why they needed else if the following pieces produce same result? Does anyone know or remember their motivation? Just curious. Axy. print('--- with else') for i in [1,2,3]: ??? print(i) else: ??? print(4) for i in []: ??? print(i) else: ??? print(5) print('--- without else') for i in [1,2,3]: ??? print(i) print(4) for i in []: ??? print(i) print(5) From drsalists at gmail.com Sat Oct 8 00:13:17 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Fri, 7 Oct 2022 21:13:17 -0700 Subject: for -- else: what was the motivation? In-Reply-To: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: The else is executed if you don't "break" out of the loop early. It cuts down on boolean flags. On Fri, Oct 7, 2022 at 8:40 PM Axy via Python-list wrote: > Hi there, > > this is rather a philosophical question, but I assume I miss something. > I don't remember I ever used else clause for years I was with python and > my expectation was it executed only if the the main body was never run. > Ha-ha! I was caught by this mental trap. > > So, seriously, why they needed else if the following pieces produce same > result? Does anyone know or remember their motivation? > > Just curious. > > Axy. > > print('--- with else') > > > for i in [1,2,3]: > print(i) > else: > print(4) > > for i in []: > print(i) > else: > print(5) > > print('--- without else') > > for i in [1,2,3]: > print(i) > print(4) > > for i in []: > print(i) > print(5) > -- > https://mail.python.org/mailman/listinfo/python-list > From gweatherby at uchc.edu Sat Oct 8 06:50:51 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Sat, 8 Oct 2022 10:50:51 +0000 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: References: Message-ID: Logging does support passing a callable, if indirectly. It only calls __str__ on the object passed if debugging is enabled. class Defer: def __init__(self,fn): self.fn = fn def __str__(self): return self.fn() def some_expensive_function(): return "hello" logging.basicConfig() logging.debug(Defer(some_expensive_function)) From: Python-list on behalf of Barry Date: Friday, October 7, 2022 at 1:30 PM To: MRAB Cc: python-list at python.org Subject: Re: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > On 7 Oct 2022, at 18:16, MRAB wrote: > > ?On 2022-10-07 16:45, Skip Montanaro wrote: >>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames >>> wrote: >>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the >>> place in calls to `logging.logger.debug()` and friends, evaluating all >>> arguments regardless of whether the logger was enabled or not. >>> >> I thought there was some discussion about whether and how to efficiently >> admit f-strings to the logging package. I'm guessing that's not gone >> anywhere (yet). > Letting you pass in a callable to call might help because that you could use lambda. Yep, that?s the obvious way to avoid expensive log data generation. Would need logging module to support that use case. Barry > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ > -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ From jorge.conforte at inpe.br Sat Oct 8 15:22:24 2022 From: jorge.conforte at inpe.br (Jorge Conrado Conforte) Date: Sat, 8 Oct 2022 16:22:24 -0300 (BRT) Subject: Polot severa figures inside a for loopin Message-ID: <111638526.9646590.1665256944028.JavaMail.zimbra@inpe.br> HI, I already use the IDL to plot data. Inside a for looping I plot and save my data and kill the window using the wdelete IDL command for close the window automatically. Now I'm using the Python to rea several netcdf 2d data. I plot my data and save it. But, I don't know how can I kill the window automatically to plot the next figure. Please how can I do this using PYthon, Thanks, Conrado From bowman at montana.com Sat Oct 8 01:49:34 2022 From: bowman at montana.com (rbowman) Date: Fri, 7 Oct 2022 23:49:34 -0600 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: On 10/7/22 21:32, Axy wrote: > So, seriously, why they needed else if the following pieces produce same > result? Does anyone know or remember their motivation? In real scenarios there would be more logic in the for block that would meet a condition and break out of the loop. If the condition is never met, the else block runs. To steal from w3schools: fruits = ["apple", "peach", "cherry"] for x in fruits: print(x) if x == "banana": break else: print("Yes we got no bananas") From michael.stemper at gmail.com Sat Oct 8 09:54:48 2022 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Sat, 8 Oct 2022 08:54:48 -0500 Subject: TkSheet In-Reply-To: <5714a18e-6d04-4359-80ce-ef816bead6e9n@googlegroups.com> References: <5714a18e-6d04-4359-80ce-ef816bead6e9n@googlegroups.com> Message-ID: On 08/10/2022 07.58, Benny Rieger wrote: > What a great work;-) > > I need a solution for save my tabel as csv. How to do that? Has someone a solution for that? Is this what you're seeking? -- Michael F. Stemper No animals were harmed in the composition of this message. From cs at cskk.id.au Sat Oct 8 18:27:55 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Sun, 9 Oct 2022 09:27:55 +1100 Subject: Polot severa figures inside a for loopin In-Reply-To: <111638526.9646590.1665256944028.JavaMail.zimbra@inpe.br> References: <111638526.9646590.1665256944028.JavaMail.zimbra@inpe.br> Message-ID: On 08Oct2022 16:22, "Jorge Conrado Conforte" wrote: >I already use the IDL to plot data. Inside a for looping I plot and >save my data and kill the window using the wdelete IDL command for >close the window automatically. >Now I'm using the Python to rea several netcdf 2d data. I plot my data and save it. But, I don't know how can I kill the window automatically to plot the next figure. >Please how can I do this using PYthon, Can you show us the code you've got to do the first part with `wdelete`? Please paste the code inline in the message; this list strips attachments such as screenshots. (And we can't copy/paste from a screenshot anyway.) And what's IDL? Can you provide a URL to it? Cheers, Cameron Simpson From axy at declassed.art Sun Oct 9 00:37:59 2022 From: axy at declassed.art (Axy) Date: Sun, 9 Oct 2022 05:37:59 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: Got it, thanks! Actually the reason I never used "else" was the violation of the rule of beauty "shortest block first". With if--else you can easily follow this rule by inverting "if" expression, but with for--else you can't. The loop body of the simplest example is already three lines, in real life things are much worse. So it was probably the first time I used "else" because I had only one line in my loop which appended data packets to the buffer and if "else" behaved as I thought it would meant I have no more data and could just return early, terminating outer loop with no other boolean logic. I have no idea why I thought so, some language might had such a semantic. Maybe my own I developed 20 years ago, but I could not invent that by myself, I definitely had some source of inspiration. Python is awesome because it's semantic is clear for the majority, but there are places that look odd. In case of "for", "else" looks logically tied with "for" clause, but actually it is not. It's tied with "break" statement and I overlooked that even after re-reading the language reference. If "else" was named like "never_broken_loop" or "nobreak", the semantic would be perfectly clear. But, what's done is done. I guess the real motivation was avoiding moving such patterns to a separate functions, say, "find_banana" where early returns make "else" absolutely unnecessary. Cheers. Axy. On 08/10/2022 06:49, rbowman wrote: > On 10/7/22 21:32, Axy wrote: >> So, seriously, why they needed else if the following pieces produce >> same result? Does anyone know or remember their motivation? > > In real scenarios there would be more logic in the for block that > would meet a condition and break out of the loop. If the condition is > never met, the else block runs. To steal from w3schools: > > > fruits = ["apple", "peach", "cherry"] > for x in fruits: > ? print(x) > ? if x == "banana": > ??? break > else: > ? print("Yes we got no bananas") > > From rosuav at gmail.com Sun Oct 9 00:47:50 2022 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 9 Oct 2022 15:47:50 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: On Sun, 9 Oct 2022 at 15:39, Axy via Python-list wrote: > > Got it, thanks! > > Actually the reason I never used "else" was the violation of the rule of > beauty "shortest block first". With if--else you can easily follow this > rule by inverting "if" expression, but with for--else you can't. The > loop body of the simplest example is already three lines, in real life > things are much worse. > That's not a rule I've ever been taught; how important is it? ChrisA From axy at declassed.art Sun Oct 9 01:04:12 2022 From: axy at declassed.art (Axy) Date: Sun, 9 Oct 2022 06:04:12 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: <52599b91-d041-e239-f663-247847056c39@declassed.art> On 09/10/2022 05:47, Chris Angelico wrote: > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list wrote: >> Got it, thanks! >> >> Actually the reason I never used "else" was the violation of the rule of >> beauty "shortest block first". With if--else you can easily follow this >> rule by inverting "if" expression, but with for--else you can't. The >> loop body of the simplest example is already three lines, in real life >> things are much worse. >> > That's not a rule I've ever been taught; how important is it? > > ChrisA It gets important if the lifetime of your project is more than three months and is extremely important if more than 10 years. But, it depends. I also might be wrong in terminology, anyway, there are many rules that make programmer's life easier, described in the literature from the old good "How to write unmaintainable code" to "The Art of Readable Code". And I hope there are a lot of recent books on this subject I did not track and read yet. Axy. From rosuav at gmail.com Sun Oct 9 01:15:29 2022 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 9 Oct 2022 16:15:29 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <52599b91-d041-e239-f663-247847056c39@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: On Sun, 9 Oct 2022 at 16:05, Axy via Python-list wrote: > > > On 09/10/2022 05:47, Chris Angelico wrote: > > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list wrote: > >> Got it, thanks! > >> > >> Actually the reason I never used "else" was the violation of the rule of > >> beauty "shortest block first". With if--else you can easily follow this > >> rule by inverting "if" expression, but with for--else you can't. The > >> loop body of the simplest example is already three lines, in real life > >> things are much worse. > >> > > That's not a rule I've ever been taught; how important is it? > > > > ChrisA > > It gets important if the lifetime of your project is more than three > months and is extremely important if more than 10 years. But, it depends. Yes, I'm aware that code readability becomes irrelevant for short-duration projects. Beside the point. I'm wondering how important it really is to have the shortest block first. > I also might be wrong in terminology, anyway, there are many rules that > make programmer's life easier, described in the literature from the old > good "How to write unmaintainable code" to "The Art of Readable Code". > And I hope there are a lot of recent books on this subject I did not > track and read yet. Also not really a justification for "shortest block first". Wanting some elaboration on that. What's the value in it? Given that for-else is an excellent, if rarely-used, construct, I would say that, *at least*, it is worth setting aside this rule for that particular situation. It is also generally worth using fewer commas than I just did. Take my advice with a grain of salt. ChrisA From axy at declassed.art Sun Oct 9 02:25:01 2022 From: axy at declassed.art (Axy) Date: Sun, 9 Oct 2022 07:25:01 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: > Yes, I'm aware that code readability becomes irrelevant for > short-duration projects. Beside the point. I'm wondering how important > it really is to have the shortest block first. > >> I also might be wrong in terminology, anyway, there are many rules that >> make programmer's life easier, described in the literature from the old >> good "How to write unmaintainable code" to "The Art of Readable Code". >> And I hope there are a lot of recent books on this subject I did not >> track and read yet. > Also not really a justification for "shortest block first". Wanting > some elaboration on that. What's the value in it? Well, the value is productivity. No need to save puzzles "what this hanging else belongs to?" regardless of semantic, which ideally should not be a puzzle as well. Code small things first and return early, same as taking a test: do easy and quick things first and boring and difficult ones later. Axy. From hjp-python at hjp.at Sun Oct 9 04:12:27 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 10:12:27 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: <20221009081227.m6merbym7yeybswy@hjp.at> On 2022-10-09 05:37:59 +0100, Axy via Python-list wrote: > Actually the reason I never used "else" was the violation of the rule > of beauty "shortest block first". That's a weird rule. I can see justifications for "most common case first" and "most special case first", but ordering the cases in an if/elif/else statement by length seems like ordering books by color: It may be pretty, but it doesn't make them easy to find. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From antoon.pardon at vub.be Sun Oct 9 06:09:17 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 12:09:17 +0200 Subject: What to use for finding as many syntax errors as possible. Message-ID: I would like a tool that tries to find as many syntax errors as possible in a python file. I know there is the risk of false positives when a tool tries to recover from a syntax error and proceeds but I would prefer that over the current python strategy of quiting after the first syntax error. I just want a tool for syntax errors. No style enforcements. Any recommandations? -- Antoon Pardon From knomenet at gmail.com Sun Oct 9 07:05:48 2022 From: knomenet at gmail.com (Michael Speer) Date: Sun, 9 Oct 2022 07:05:48 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: >Well, the value is productivity. No need to save puzzles "what this >hanging else belongs to?" if you get to the point where it's hard to tell which else lines up with which if or for statement, I would suggest breaking things out into well-named helper functions rather than worrying over ordering by block size On Sun, Oct 9, 2022 at 2:26 AM Axy via Python-list wrote: > > > Yes, I'm aware that code readability becomes irrelevant for > > short-duration projects. Beside the point. I'm wondering how important > > it really is to have the shortest block first. > > > >> I also might be wrong in terminology, anyway, there are many rules that > >> make programmer's life easier, described in the literature from the old > >> good "How to write unmaintainable code" to "The Art of Readable Code". > >> And I hope there are a lot of recent books on this subject I did not > >> track and read yet. > > Also not really a justification for "shortest block first". Wanting > > some elaboration on that. What's the value in it? > > Well, the value is productivity. No need to save puzzles "what this > hanging else belongs to?" regardless of semantic, which ideally should > not be a puzzle as well. Code small things first and return early, same > as taking a test: do easy and quick things first and boring and > difficult ones later. > > Axy. > -- > https://mail.python.org/mailman/listinfo/python-list > From avi.e.gross at gmail.com Sun Oct 9 11:49:55 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 11:49:55 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: Anton There likely are such programs out there but are there universal agreements on how to figure out when a new safe zone of code starts where error testing can begin? For example a file full of function definitions might find an error in function 1 and try to find the end of that function and resume checking the next function. But what if a function defines local functions within it? What if the mistake in one line of code could still allow checking the next line rather than skipping it all? My guess is that finding 100 errors might turn out to be misleading. If you fix just the first, many others would go away. If you spell a variable name wrong when declaring it, a dozen uses of the right name may cause errors. Should you fix the first or change all later ones? On Sun, Oct 9, 2022, 6:11 AM Antoon Pardon wrote: > I would like a tool that tries to find as many syntax errors as possible > in a python file. I know there is the risk of false positives when a > tool tries to recover from a syntax error and proceeds but I would > prefer that over the current python strategy of quiting after the first > syntax error. I just want a tool for syntax errors. No style > enforcements. Any recommandations? -- Antoon Pardon > -- > https://mail.python.org/mailman/listinfo/python-list > From hjp-python at hjp.at Sun Oct 9 12:17:18 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 18:17:18 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <20221009161718.n5fokglnkw3nslnk@hjp.at> On 2022-10-09 12:09:17 +0200, Antoon Pardon wrote: > I would like a tool that tries to find as many syntax errors as possible in > a python file. I know there is the risk of false positives when a tool tries > to recover from a syntax error and proceeds but I would prefer that over the > current python strategy of quiting after the first syntax error. I just want > a tool for syntax errors. No style enforcements. Any recommandations? There seems to have been increased interest in good error recovery over the last years. I thought I had bookmarked a bunch of projects, but the only one I can find right now is Lezer (https://marijnhaverbeke.nl/blog/lezer.html) which is part of the CodeMirror (https://codemirror.net/) editor. Python is listed as a currently supported language, so you might want to check that out. Disclaimer: I haven't used CodeMirror, so I can't say anything about its quality. The blog entry about Lezer was interesting, though. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From avi.e.gross at gmail.com Sun Oct 9 12:18:09 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 12:18:09 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Smallest code blocks first may be a more modern invention. Some would argue for a rule related to efficiency of execution. When you have multiple blocks as in an if-else or case statement with multiple choices, that you order the most common cases first. Those shorten execution more often than the rarer cases especially the ones that should never happen. There are obvious exceptions like the default having to be last, albeit some languages allow the default to be inserted anywhere visually even if the code sort of runs last. But negating a condition so smaller code appears first may have some cost. I mean if !function() may be slower as the negating is an extra step. But it may be even slower if the inversion is done using a wrapper function that simply inverts the return value from the other function. I think sometimes a comment placed carefully that explains the code and logic in concise form is a simpler approach that can be followed by a big chunk then little chunk without loss of readability. In the original example the else part can be mentioned before the loop as a sort of reminder. In my experience, the size of code often varies within a project so a smaller chunk may grow as requirements change, such as adding debug or logging, and large chunks can shrink as common parts of the code get extracted into functions. So not a rule but realistically not always a bad idea to write code in a way that draws the attention of readers along the main path of execution and perhaps not showing all the checking for odd cases first. I mean as an example if the argument is of type text then do stuff, else if a number else if a symbol else if empty ... On Sun, Oct 9, 2022, 1:18 AM Chris Angelico wrote: > On Sun, 9 Oct 2022 at 16:05, Axy via Python-list > wrote: > > > > > > On 09/10/2022 05:47, Chris Angelico wrote: > > > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list < > python-list at python.org> wrote: > > >> Got it, thanks! > > >> > > >> Actually the reason I never used "else" was the violation of the rule > of > > >> beauty "shortest block first". With if--else you can easily follow > this > > >> rule by inverting "if" expression, but with for--else you can't. The > > >> loop body of the simplest example is already three lines, in real life > > >> things are much worse. > > >> > > > That's not a rule I've ever been taught; how important is it? > > > > > > ChrisA > > > > It gets important if the lifetime of your project is more than three > > months and is extremely important if more than 10 years. But, it depends. > > Yes, I'm aware that code readability becomes irrelevant for > short-duration projects. Beside the point. I'm wondering how important > it really is to have the shortest block first. > > > I also might be wrong in terminology, anyway, there are many rules that > > make programmer's life easier, described in the literature from the old > > good "How to write unmaintainable code" to "The Art of Readable Code". > > And I hope there are a lot of recent books on this subject I did not > > track and read yet. > > Also not really a justification for "shortest block first". Wanting > some elaboration on that. What's the value in it? > > Given that for-else is an excellent, if rarely-used, construct, I > would say that, *at least*, it is worth setting aside this rule for > that particular situation. It is also generally worth using fewer > commas than I just did. Take my advice with a grain of salt. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From Karsten.Hilbert at gmx.net Sun Oct 9 12:18:39 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Sun, 9 Oct 2022 18:18:39 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: Am Sun, Oct 09, 2022 at 05:37:59AM +0100 schrieb Axy via Python-list: > Python is awesome because it's semantic is clear for the majority, but there are places > that look odd. In case of "for", "else" looks logically tied with "for" clause, but > actually it is not. It's tied with "break" statement and I overlooked that even after > re-reading the language reference. If "else" was named like "never_broken_loop" or > "nobreak", the semantic would be perfectly clear. But, what's done is done. Or, "eventually". Sadly, "finally" is already taken, and with slightly different semantics... Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From rosuav at gmail.com Sun Oct 9 12:29:00 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 03:29:00 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 03:22, Avi Gross wrote: > > Smallest code blocks first may be a more modern invention. > > Some would argue for a rule related to efficiency of execution. When you > have multiple blocks as in an if-else or case statement with multiple > choices, that you order the most common cases first. Those shorten > execution more often than the rarer cases especially the ones that should > never happen. > Seems fairly dubious and full of special-cases. If you want to follow that rule, it should be easy enough to still permit for-else clauses. It's an extremely weak argument against for-else. ChrisA From avi.e.gross at gmail.com Sun Oct 9 12:34:22 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 12:34:22 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <20221009081227.m6merbym7yeybswy@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> Message-ID: Since many languages allow placing multiple statements on one line or spreading one over many lines, it seems that the number of lines in code can be adjusted. If I have a line like: Alpha, beta, gamma, delta = 1, 2, 3, 4 Could that be rewritten as 4 or more lines? I have seen programmers who have taken an elegant pipeline I have built apart and made it into many lines of code reassignment the value of each step to the same or different variables and other ways of lengthening or obscuring my intent. So although size may matter, so can sighs. On Sun, Oct 9, 2022, 4:24 AM Peter J. Holzer wrote: > On 2022-10-09 05:37:59 +0100, Axy via Python-list wrote: > > Actually the reason I never used "else" was the violation of the rule > > of beauty "shortest block first". > > That's a weird rule. > > I can see justifications for "most common case first" and "most special > case first", but ordering the cases in an if/elif/else statement by > length seems like ordering books by color: It may be pretty, but it > doesn't make them easy to find. > > hp > > -- > _ | Peter J. Holzer | Story must make more sense than reality. > |_|_) | | > | | | hjp at hjp.at | -- Charles Stross, "Creative writing > __/ | http://www.hjp.at/ | challenge!" > -- > https://mail.python.org/mailman/listinfo/python-list > From avi.e.gross at gmail.com Sun Oct 9 12:44:34 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 12:44:34 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Chris, I was not arguing that at all. I was saying some rationales about how to order choices exist based on ideas like efficiency or other considerations. Sometimes people are mistaken as something may take constant time as implemented. And yes, many rules have countless exceptions. For example, if something is expected to rarely or never happen, code within that branch may not be needed to be optimized in any way as long as it works in the remote chance it is called. I think what was suggested here is more about code readability considerations and for some of us, making us stand on our heads to puzzle things out is harder than ordering longer items ... On Sun, Oct 9, 2022, 12:30 PM Chris Angelico wrote: > On Mon, 10 Oct 2022 at 03:22, Avi Gross wrote: > > > > Smallest code blocks first may be a more modern invention. > > > > Some would argue for a rule related to efficiency of execution. When you > > have multiple blocks as in an if-else or case statement with multiple > > choices, that you order the most common cases first. Those shorten > > execution more often than the rarer cases especially the ones that should > > never happen. > > > > Seems fairly dubious and full of special-cases. If you want to follow > that rule, it should be easy enough to still permit for-else clauses. > It's an extremely weak argument against for-else. > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From rosuav at gmail.com Sun Oct 9 12:51:21 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 03:51:21 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 03:46, Avi Gross wrote: > > Chris, I was not arguing that at all. Maybe not intentionally, but you did lend a lot of weight to that argument :) ChrisA From axy at declassed.art Sun Oct 9 12:53:55 2022 From: axy at declassed.art (Axy) Date: Sun, 9 Oct 2022 17:53:55 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> Message-ID: <88e4cd85-86b6-6a0e-4488-40d366769a4b@declassed.art> > Since many languages allow placing multiple statements on one line or > spreading one over many lines, it seems that the number of lines in code > can be adjusted. > > If I have a line like: > > Alpha, beta, gamma, delta = 1, 2, 3, 4 > > Could that be rewritten as 4 or more lines? Surely! Especially if you're paid for SLOC :-))) By the way, does "else" clause after affect cyclomatic complexity metric? I mean "for" loops. Axy. From hjp-python at hjp.at Sun Oct 9 12:56:29 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 18:56:29 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: <20221009165629.5cphjckz4zzpnmgz@hjp.at> On 2022-10-09 12:18:09 -0400, Avi Gross wrote: > Smallest code blocks first may be a more modern invention. > > Some would argue for a rule related to efficiency of execution. When you > have multiple blocks as in an if-else or case statement with multiple > choices, that you order the most common cases first. Those shorten > execution more often than the rarer cases especially the ones that should > never happen. Those of us who started programming on 8 bit homecomputers of course have efficiency always at the back of their heads, but I find this > So not a rule but realistically not always a bad idea to write code in a > way that draws the attention of readers along the main path of execution > and perhaps not showing all the checking for odd cases first. much more important. Putting the main path first makes it easier to understand what the code is supposed to do normally. All those pesky exceptions are in the "small print" below. There is of course the opposite view that you should just get all of the confounding factors out of the way first, so that the default is also the common case. I also do that sometimes, but then I don't hide this in in an else: clause but do something like this: for item in whatever: if not_this_one(item): continue if neither_this_one(item): continue if cant_continue(item): break if oopsie(): raise SomeError() do_something_with(item) and_some_more(item) we_are_done(item) which shows visually what the main purpose of the loop (or function or other block) is. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From antoon.pardon at vub.be Sun Oct 9 12:59:36 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 18:59:36 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Op 9/10/2022 om 17:49 schreef Avi Gross: > My guess is that finding 100 errors might turn out to be misleading. If you > fix just the first, many others would go away. At this moment I would prefer a tool that reported 100 errors, which would allow me to easily correct 10 real errors, over the python strategy which quits after having found one syntax error. -- Antoon. From hjp-python at hjp.at Sun Oct 9 13:14:14 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 19:14:14 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> Message-ID: <20221009171414.n4gdtqvk5lzepblm@hjp.at> On 2022-10-09 12:34:22 -0400, Avi Gross wrote: > I have seen programmers who have taken an elegant pipeline I have built > apart and made it into many lines of code reassignment the value of each > step to the same or different variables and other ways of lengthening or > obscuring my intent. I have certainly done that (not with your code, AFAIK). The problem with those beautiful one-liners is that they are really hard to debug. So if I can't convince myself that they are correct just by reading them I have to split them over multiple lines so I can add breakpoints or log messages. Of course I could put it together again afterwards, but I would argue that if I didn't understand it the first time it's probably better to leave it in its more verbose and debuggable state. Of course I have also done the opposite: Taken some messy and complicated code and simplified it into a simple generator expression. In fact I would say that I code tends to be shorter after I fixed a bug than before. > So although size may matter, so can sighs. :-) hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From list1 at tompassin.net Sun Oct 9 12:59:09 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sun, 9 Oct 2022 12:59:09 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <20221009161718.n5fokglnkw3nslnk@hjp.at> References: <20221009161718.n5fokglnkw3nslnk@hjp.at> Message-ID: https://stackoverflow.com/questions/4284313/how-can-i-check-the-syntax-of-python-script-without-executing-it People seemed especially enthusiastic about the one-liner from jmd_dk. On 10/9/2022 12:17 PM, Peter J. Holzer wrote: > On 2022-10-09 12:09:17 +0200, Antoon Pardon wrote: >> I would like a tool that tries to find as many syntax errors as possible in >> a python file. I know there is the risk of false positives when a tool tries >> to recover from a syntax error and proceeds but I would prefer that over the >> current python strategy of quiting after the first syntax error. I just want >> a tool for syntax errors. No style enforcements. Any recommandations? > > There seems to have been increased interest in good error recovery over > the last years. I thought I had bookmarked a bunch of projects, but the > only one I can find right now is Lezer > (https://marijnhaverbeke.nl/blog/lezer.html) which is part of the > CodeMirror (https://codemirror.net/) editor. Python is listed as a > currently supported language, so you might want to check that out. > > Disclaimer: I haven't used CodeMirror, so I can't say anything about > its quality. The blog entry about Lezer was interesting, though. > > hp > > From Karsten.Hilbert at gmx.net Sun Oct 9 13:23:41 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Sun, 9 Oct 2022 19:23:41 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: > Op 9/10/2022 om 17:49 schreef Avi Gross: > >My guess is that finding 100 errors might turn out to be misleading. If you > >fix just the first, many others would go away. > > At this moment I would prefer a tool that reported 100 errors, which would > allow me to easily correct 10 real errors, over the python strategy which quits > after having found one syntax error. But the point is: you can't (there is no way to) be sure the 9+ errors really are errors. Unless you further constrict what sorts of errors you are looking for and what margin of error or leeway for false positives you want to allow. Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From hjp-python at hjp.at Sun Oct 9 13:29:32 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 19:29:32 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <20221009161718.n5fokglnkw3nslnk@hjp.at> Message-ID: <20221009172932.4wud7mixboy6rvhl@hjp.at> On 2022-10-09 12:59:09 -0400, Thomas Passin wrote: > https://stackoverflow.com/questions/4284313/how-can-i-check-the-syntax-of-python-script-without-executing-it > > People seemed especially enthusiastic about the one-liner from jmd_dk. I don't think that one-liner solves Antoon's requirement of continuing after an error. It uses just the normal python parser so it has exactly the same limitations. Some of the mentioned tools may do what Antoon wants, though. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Sun Oct 9 13:36:48 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 19:36:48 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: <20221009173648.im7qhjnmvq4vsg5j@hjp.at> On 2022-10-09 19:23:41 +0200, Karsten Hilbert wrote: > Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: > > Op 9/10/2022 om 17:49 schreef Avi Gross: > > >My guess is that finding 100 errors might turn out to be misleading. If you > > >fix just the first, many others would go away. > > > > At this moment I would prefer a tool that reported 100 errors, which would > > allow me to easily correct 10 real errors, over the python strategy which quits > > after having found one syntax error. > > But the point is: you can't (there is no way to) be sure the > 9+ errors really are errors. As a human who knows Python in many cases you can be sure. Sometimes you aren't sure, then you leave that one for the next iteration. No big deal. This isn't the 1960s when you sent your punched cards in and got the result back next week. So neither the parser nor you need to be perfect. Just better than one error at a time. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From antoon.pardon at vub.be Sun Oct 9 13:51:12 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 19:51:12 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: Op 9/10/2022 om 19:23 schreef Karsten Hilbert: > Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: > >> Op 9/10/2022 om 17:49 schreef Avi Gross: >>> My guess is that finding 100 errors might turn out to be misleading. If you >>> fix just the first, many others would go away. >> At this moment I would prefer a tool that reported 100 errors, which would >> allow me to easily correct 10 real errors, over the python strategy which quits >> after having found one syntax error. > But the point is: you can't (there is no way to) be sure the > 9+ errors really are errors. > > Unless you further constrict what sorts of errors you are > looking for and what margin of error or leeway for false > positives you want to allow. Look when I was at the university we had to program in Pascal and the compilor we used continued parsing until the end. Sure there were times that after a number of reported errors the number of false positives became so high it was useless trying to find the remaining true ones, but it still was more efficient to correct the obvious ones, than to only correct the first one. I don't need to be sure. Even the occasional wrong correction is probably still more efficient than quiting after the first syntax error. -- Antoon. From gweatherby at uchc.edu Sun Oct 9 14:00:51 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Sun, 9 Oct 2022 18:00:51 +0000 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: PyCharm. Does a good job of separating these are really errors from do you really mean that warnings from this word is spelled right. https://www.jetbrains.com/pycharm/ From: Python-list on behalf of Antoon Pardon Date: Sunday, October 9, 2022 at 6:11 AM To: python-list at python.org Subject: What to use for finding as many syntax errors as possible. *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** I would like a tool that tries to find as many syntax errors as possible in a python file. I know there is the risk of false positives when a tool tries to recover from a syntax error and proceeds but I would prefer that over the current python strategy of quiting after the first syntax error. I just want a tool for syntax errors. No style enforcements. Any recommandations? -- Antoon Pardon -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!kxDZilNf74VILuntVEzVZ4Wjv6RPr4JUbGpWrURDJ3CtDNAi9szBWweqrDM-uHy-o_Sncgrm2BmJIRksmxSG_LGVbBU$ From jschwar at sbcglobal.net Sun Oct 9 14:47:53 2022 From: jschwar at sbcglobal.net (jschwar at sbcglobal.net) Date: Sun, 9 Oct 2022 13:47:53 -0500 Subject: AWS upload script written in python - verify number of processes used References: <000001d8dc0f$a4637030$ed2a5090$.ref@sbcglobal.net> Message-ID: <000001d8dc0f$a4637030$ed2a5090$@sbcglobal.net> I have an AWS upload script to upload to my S3 bucket and I have it configured to use 6 processes. How can I verify that it's using 6 processes to do the upload? I have wireshark installed, but I'm not very familiar with it. I also have tried tasklist, but that doesn't tell me what I want to know either. Does anyone know how to check this? From python at mrabarnett.plus.com Sun Oct 9 14:51:19 2022 From: python at mrabarnett.plus.com (MRAB) Date: Sun, 9 Oct 2022 19:51:19 +0100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: <905a9194-718c-cb75-1f9e-7b12b0774e50@mrabarnett.plus.com> On 2022-10-09 18:51, Antoon Pardon wrote: > > > Op 9/10/2022 om 19:23 schreef Karsten Hilbert: >> Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: >> >>> Op 9/10/2022 om 17:49 schreef Avi Gross: >>>> My guess is that finding 100 errors might turn out to be misleading. If you >>>> fix just the first, many others would go away. >>> At this moment I would prefer a tool that reported 100 errors, which would >>> allow me to easily correct 10 real errors, over the python strategy which quits >>> after having found one syntax error. >> But the point is: you can't (there is no way to) be sure the >> 9+ errors really are errors. >> >> Unless you further constrict what sorts of errors you are >> looking for and what margin of error or leeway for false >> positives you want to allow. > > Look when I was at the university we had to program in Pascal and > the compilor we used continued parsing until the end. Sure there > were times that after a number of reported errors the number of > false positives became so high it was useless trying to find the > remaining true ones, but it still was more efficient to correct the > obvious ones, than to only correct the first one. > > I don't need to be sure. Even the occasional wrong correction > is probably still more efficient than quiting after the first > syntax error. > When I did some programming in COBOL, a single omitted "." would completely confuse the compiler and it was best to fix that one error and then try again. On the other hand, TurboPascal would also stop on the first error and put the cursor at the error position in the IDE, but as it compiled quickly, it wasn't a problem. It was no slower than it would've been if it had found multiple errors and you pressed a key to advance to the next error. From jschwar at sbcglobal.net Sun Oct 9 14:52:23 2022 From: jschwar at sbcglobal.net (jschwar at sbcglobal.net) Date: Sun, 9 Oct 2022 13:52:23 -0500 Subject: AWS upload script written in python - verify number of processes used Message-ID: <000501d8dc10$451967f0$cf4c37d0$@sbcglobal.net> Sorry, I forgot to mention that I'm using Windows 10 64-bit. From: jschwar at sbcglobal.net Sent: Sunday, October 9, 2022 1:48 PM To: 'python-list at python.org' Subject: AWS upload script written in python - verify number of processes used I have an AWS upload script to upload to my S3 bucket and I have it configured to use 6 processes. How can I verify that it's using 6 processes to do the upload? I have wireshark installed, but I'm not very familiar with it. I also have tried tasklist, but that doesn't tell me what I want to know either. Does anyone know how to check this? From avi.e.gross at gmail.com Sun Oct 9 14:54:52 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 14:54:52 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Fair enough, Chris. There may be some overlap with the size of code for the most common cases but sometimes the opposite as those may be more complex to deal with. A reality for many programmers today is to not micromanage too early as things are often fast enough and any tweaking is best done only in critical areas. The emphasis may be on the programmer experience in writing fast code with fewer errors. Perhaps secondary but often important is making the code maintainable and in my experience that can often be best done by choosing meaningful names and brief selective comments than by worrying about the size of blocks of code. But others obviously preach what they think works for them even when it may constrain others more than it helps. I have seen people suggest that all variables have short names like a3 but that does not mean it improves anything other than the size of the code and parsing it. The loss in readability and so on probably is worse. On Sun, Oct 9, 2022, 12:53 PM Chris Angelico wrote: > On Mon, 10 Oct 2022 at 03:46, Avi Gross wrote: > > > > Chris, I was not arguing that at all. > > Maybe not intentionally, but you did lend a lot of weight to that argument > :) > > ChrisA > -- > https://mail.python.org/mailman/listinfo/python-list > From avi.e.gross at gmail.com Sun Oct 9 15:18:19 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 15:18:19 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: Antoon, it may also relate to an interpreter versus compiler issue. Something like a compiler for C does not do anything except write code in an assembly language. It can choose to keep going after an error and start looking some more from a less stable place. Interpreters for Python have to catch interrupts as they go and often run code in small batches. Continuing to evaluate after an error could cause weird effects. So what you want is closer to a lint program that does not run code at all, or merely writes pseudocode to a file to be run faster later. Many languages now have blocks of code that are not really be evaluated till later. Some code is built on the fly. And some errors are not errors at first. Many languages let you not declare a variable before using it or allow it to change types. In some, the text is lazily evaluated as late as possible. I will say that often enough a program could report more possible errors. Putting your code into multiple files and modules may mean you could cleanly evaluate the code and return multiple errors from many modules as long as they are distinct. Finding all errors is not possible if recovery from one is not guaranteed. Take a language that uses a semicolon to end a statement. If absent usually there would be some error but often something on the next line. Your evaluator could do an experiment and add a semicolon and try again. This might work 90% of the time but sometimes the error was not ending the line with a backslash to make it continue properly, or an indentation issue and even spelling error. No guarantees. Is it that onerous to fix one thing and run it again? It was once when you handed in punch cards and waited a day or on very busy machines. On Sun, Oct 9, 2022, 1:03 PM Antoon Pardon wrote: > > > Op 9/10/2022 om 17:49 schreef Avi Gross: > > My guess is that finding 100 errors might turn out to be misleading. If > you > > fix just the first, many others would go away. > > At this moment I would prefer a tool that reported 100 errors, which would > allow me to easily correct 10 real errors, over the python strategy which > quits > after having found one syntax error. > > -- > Antoon. > > -- > https://mail.python.org/mailman/listinfo/python-list > From avi.e.gross at gmail.com Sun Oct 9 15:32:13 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 15:32:13 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <20221009171414.n4gdtqvk5lzepblm@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> Message-ID: Peter, There can be excellent reasons to undo a pipeline like I described. I often write it carefully in smaller chunks while debugging and make it more elegant later ... But someone amused me by explaining they were going to let people believe the code was written by them so it had to fit their style and abilities. That meant removing most of my comments, renaming some variables, taking out code that checked things like whether a file existed before opening it and of course no pipelines. It had to be downgraded and had I known, I could have easily given them code written as if it was in some poorer language. Python has idioms often used in making pipes of a sort but in languages with other forms, such as R, debugging is not that difficult as you can insert functions in middle of a pipeline that print what you want but return the data structure they were fed for the next step in the pipeline. When done, remove the lines with such entries or change the function definition or something like that. Objects used as pipelines do not do this as easily as you may need to add methods ... On Sun, Oct 9, 2022, 1:17 PM Peter J. Holzer wrote: > On 2022-10-09 12:34:22 -0400, Avi Gross wrote: > > I have seen programmers who have taken an elegant pipeline I have built > > apart and made it into many lines of code reassignment the value of each > > step to the same or different variables and other ways of lengthening or > > obscuring my intent. > > I have certainly done that (not with your code, AFAIK). The problem with > those beautiful one-liners is that they are really hard to debug. So if > I can't convince myself that they are correct just by reading them I > have to split them over multiple lines so I can add breakpoints or log > messages. Of course I could put it together again afterwards, but I > would argue that if I didn't understand it the first time it's probably > better to leave it in its more verbose and debuggable state. > > Of course I have also done the opposite: Taken some messy and > complicated code and simplified it into a simple generator expression. > In fact I would say that I code tends to be shorter after I fixed a bug > than before. > > > > So although size may matter, so can sighs. > > :-) > > hp > > -- > _ | Peter J. Holzer | Story must make more sense than reality. > |_|_) | | > | | | hjp at hjp.at | -- Charles Stross, "Creative writing > __/ | http://www.hjp.at/ | challenge!" > -- > https://mail.python.org/mailman/listinfo/python-list > From avi.e.gross at gmail.com Sun Oct 9 15:44:56 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 9 Oct 2022 15:44:56 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: I will say that those of us meaning me, who express reservations are not arguing it is a bad idea to get more info in one sweep. Many errors come in bunches. If I keep calling some function with the wrong number or type of arguments, it may be the same in a dozen places in my code. The first error report may make me search for the others places so I fix it all at once. Telling me where some instances are might speed that a bit. As long as it is understood that further errors are a heuristic and possibly misleading, fine. But an error like setting the size of a fixed length data structure to the right size may result in oodles of errors about being out of range that magically get fixed by one change. Sometimes too much info just gives you a headache. But a tool like you described could have uses even if imperfect. If you are teaching a course and students submit programs, could you grade the one with a single error higher than one with 5 errors shown imperfectly and fail the one with 600? On Sun, Oct 9, 2022, 1:53 PM Antoon Pardon wrote: > > > Op 9/10/2022 om 19:23 schreef Karsten Hilbert: > > Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: > > > >> Op 9/10/2022 om 17:49 schreef Avi Gross: > >>> My guess is that finding 100 errors might turn out to be misleading. > If you > >>> fix just the first, many others would go away. > >> At this moment I would prefer a tool that reported 100 errors, which > would > >> allow me to easily correct 10 real errors, over the python strategy > which quits > >> after having found one syntax error. > > But the point is: you can't (there is no way to) be sure the > > 9+ errors really are errors. > > > > Unless you further constrict what sorts of errors you are > > looking for and what margin of error or leeway for false > > positives you want to allow. > > Look when I was at the university we had to program in Pascal and > the compilor we used continued parsing until the end. Sure there > were times that after a number of reported errors the number of > false positives became so high it was useless trying to find the > remaining true ones, but it still was more efficient to correct the > obvious ones, than to only correct the first one. > > I don't need to be sure. Even the occasional wrong correction > is probably still more efficient than quiting after the first > syntax error. > > -- > Antoon. > -- > https://mail.python.org/mailman/listinfo/python-list > From antoon.pardon at vub.be Sun Oct 9 15:46:13 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 21:46:13 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Op 9/10/2022 om 21:18 schreef Avi Gross: > Antoon, it may also relate to an interpreter versus compiler issue. > > Something like a compiler for C does not do anything except write code in > an assembly language. It can choose to keep going after an error and start > looking some more from a less stable place. > > Interpreters for Python have to catch interrupts as they go and often run > code in small batches. Continuing to evaluate after an error could cause > weird effects. > > So what you want is closer to a lint program that does not run code at all, > or merely writes pseudocode to a file to be run faster later. I just want a parser that doesn't give up on encoutering the first syntax error. Maybe do some semantic checking like checking the number of parameters. > I will say that often enough a program could report more possible errors. > Putting your code into multiple files and modules may mean you could > cleanly evaluate the code and return multiple errors from many modules as > long as they are distinct. Finding all errors is not possible if recovery > from one is not guaranteed. I don't need it to find all errors. As long as it reasonably accuratly finds a significant number of them. > Is it that onerous to fix one thing and run it again? It was once when you > handed in punch cards and waited a day or on very busy machines. Yes I find it onerous, especially since I have a pipeline with unit tests and other tools that all have to redo their work each time a bug is corrected. -- Antoon. From antoon.pardon at vub.be Sun Oct 9 15:46:26 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 21:46:26 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: <6faf4753-0fc7-d558-8f18-2ab13cc0a6d4@vub.be> Op 9/10/2022 om 21:18 schreef Avi Gross: > Antoon, it may also relate to an interpreter versus compiler issue. > > Something like a compiler for C does not do anything except write code in > an assembly language. It can choose to keep going after an error and start > looking some more from a less stable place. > > Interpreters for Python have to catch interrupts as they go and often run > code in small batches. Continuing to evaluate after an error could cause > weird effects. > > So what you want is closer to a lint program that does not run code at all, > or merely writes pseudocode to a file to be run faster later. I just want a parser that doesn't give up on encoutering the first syntax error. Maybe do some semantic checking like checking the number of parameters. > I will say that often enough a program could report more possible errors. > Putting your code into multiple files and modules may mean you could > cleanly evaluate the code and return multiple errors from many modules as > long as they are distinct. Finding all errors is not possible if recovery > from one is not guaranteed. I don't need it to find all errors. As long as it reasonably accuratly finds a significant number of them. > Is it that onerous to fix one thing and run it again? It was once when you > handed in punch cards and waited a day or on very busy machines. Yes I find it onerous, especially since I have a pipeline with unit tests and other tools that all have to redo their work each time a bug is corrected. -- Antoon. From hjp-python at hjp.at Sun Oct 9 15:46:47 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 21:46:47 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: <20221009194647.tp7kj6nj34gpo7bf@hjp.at> On 2022-10-09 15:18:19 -0400, Avi Gross wrote: > Antoon, it may also relate to an interpreter versus compiler issue. > > Something like a compiler for C does not do anything except write code in > an assembly language. It can choose to keep going after an error and start > looking some more from a less stable place. > > Interpreters for Python have to catch interrupts as they go and often run > code in small batches. Continuing to evaluate after an error could cause > weird effects. I don't think this is really an issue. A python file is completely compiled to byte code before execution starts. It's true that a syntax error before an import prevents that import, but since imports are usually at the start of a file, a syntax error will only rarely prevent the import (and files intended to be imported generally don't have weird side effects anyway). One issue is could be that compilers which generate executables are generally thorough and slow, while the compilers which generate byte-code for immediate consumption by an interpreter are generally simple and fast. So there is more incentive for the former to discover as many errors as possible and they are also better equipped to do this. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Sun Oct 9 16:02:27 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 9 Oct 2022 22:02:27 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> Message-ID: <20221009200227.dzmu2thwcsunees3@hjp.at> On 2022-10-09 15:32:13 -0400, Avi Gross wrote: > and of course no pipelines. Since you've now used that term repeatedly: What is a pipeline in Python? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From antoon.pardon at vub.be Sun Oct 9 16:02:47 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 9 Oct 2022 22:02:47 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: Op 9/10/2022 om 21:44 schreef Avi Gross: > But an error like setting the size of a fixed length data structure to the > right size may result in oodles of errors about being out of range that > magically get fixed by one change. Sometimes too much info just gives you a > headache. So? The user of such a tool doesn't need to go through all the provided information. If after correcting a few errors, the users find the rest of the information gives him a headache, he can just ignore all that and just run a new iteration. -- Antoon Pardon From barry at barrys-emacs.org Sun Oct 9 16:09:51 2022 From: barry at barrys-emacs.org (Barry) Date: Sun, 9 Oct 2022 21:09:51 +0100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: > On 9 Oct 2022, at 18:54, Antoon Pardon wrote: > > ? > > Op 9/10/2022 om 19:23 schreef Karsten Hilbert: >> Am Sun, Oct 09, 2022 at 06:59:36PM +0200 schrieb Antoon Pardon: >> >>> Op 9/10/2022 om 17:49 schreef Avi Gross: >>>> My guess is that finding 100 errors might turn out to be misleading. If you >>>> fix just the first, many others would go away. >>> At this moment I would prefer a tool that reported 100 errors, which would >>> allow me to easily correct 10 real errors, over the python strategy which quits >>> after having found one syntax error. >> But the point is: you can't (there is no way to) be sure the >> 9+ errors really are errors. >> >> Unless you further constrict what sorts of errors you are >> looking for and what margin of error or leeway for false >> positives you want to allow. > > Look when I was at the university we had to program in Pascal and > the compilor we used continued parsing until the end. Sure there > were times that after a number of reported errors the number of > false positives became so high it was useless trying to find the > remaining true ones, but it still was more efficient to correct the > obvious ones, than to only correct the first one. If it?s very fast to syntax check then one at a time is fine. Python is very fast to syntax check so I personal do not need the multi error version. My editor has syntax check on a key and it?s instant to drop me a syntax error. Barry > > I don't need to be sure. Even the occasional wrong correction > is probably still more efficient than quiting after the first > syntax error. > > -- > Antoon. > -- > https://mail.python.org/mailman/listinfo/python-list > From Karsten.Hilbert at gmx.net Sun Oct 9 16:46:44 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Sun, 9 Oct 2022 22:46:44 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> Message-ID: Am Sun, Oct 09, 2022 at 07:51:12PM +0200 schrieb Antoon Pardon: > >But the point is: you can't (there is no way to) be sure the > >9+ errors really are errors. > > > >Unless you further constrict what sorts of errors you are > >looking for and what margin of error or leeway for false > >positives you want to allow. > > Look when I was at the university we had to program in Pascal and > the compilor we used continued parsing until the end. Sure there > were times that after a number of reported errors the number of > false positives became so high it was useless trying to find the > remaining true ones, but it still was more efficient to correct the > obvious ones, than to only correct the first one. > > I don't need to be sure. Even the occasional wrong correction > is probably still more efficient than quiting after the first > syntax error. A-ha, so you further defined your context. Under which I can agree to the objective :-) Best, Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From rosuav at gmail.com Sun Oct 9 18:23:27 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 09:23:27 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Message-ID: On Mon, 10 Oct 2022 at 06:50, Antoon Pardon wrote: > I just want a parser that doesn't give up on encoutering the first syntax > error. Maybe do some semantic checking like checking the number of parameters. That doesn't make sense though. It's one thing to keep going after finding a non-syntactic error, but an error of syntax *by definition* makes parsing the rest of the file dubious. What would it even *mean* to not give up? How should it interpret the following lines of code? All it can do is report the error. You know, if you'd not made this thread, the time you saved would have been enough for quite a few iterations of "fix one syntactic error, run it again to find the next". ChrisA From cs at cskk.id.au Sun Oct 9 18:45:12 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 10 Oct 2022 09:45:12 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> References: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Message-ID: On 09Oct2022 21:46, Antoon Pardon wrote: >>Is it that onerous to fix one thing and run it again? It was once when >>you >>handed in punch cards and waited a day or on very busy machines. > >Yes I find it onerous, especially since I have a pipeline with unit tests >and other tools that all have to redo their work each time a bug is >corrected. It is easy to get the syntax right before submitting to such a pipeline. I usually run a linter on my code for serious commits, and I've got a `lint1` alias which basicly runs the short fast flavour of that which does a syntax check and the very fast less thorough lint phase. I say this just to ease your write/run-tests cycle. Regarding your main request, had you considered writing your own wrapper tool? Something which ran something like: python -We:invalid -m py_compile your_python_file.py If there's an error, report it, then make a new file commencing with the next unindented line after the error, with all preceeding lines commented out (to keep the line numbers the same). Then run the check again. Repeat until the file's empty or there are no errors. This doesn't sound very complex. Cheers, Cameron Simpson From PythonList at DancesWithMice.info Sun Oct 9 19:40:44 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 10 Oct 2022 12:40:44 +1300 Subject: for -- else: what was the motivation? In-Reply-To: <20221009165629.5cphjckz4zzpnmgz@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: On Sun, 9 Oct 2022 at 15:39, Axy via Python-list wrote: > "shortest block first" Have never heard this advice before. Kind-of rankled with me, as it did for others. Enquiring minds want to know... Played Duck, duck, go on this: zero hits amongst a pile of similar phrases - turns-out there's an algorithm with a similar name, but not related, and an electronics approach (way too 'low' a level for translation to us though). Tried prefixing with "program" but no such advice to programmers or program[me] designers. Tried prefixing with "python", but equal lack of joy. Would OP please quote source? On 10/10/2022 05.56, Peter J. Holzer wrote: > On 2022-10-09 12:18:09 -0400, Avi Gross wrote: >> Smallest code blocks first may be a more modern invention. None of the recent-grads or new-hires I've asked this morning (it's already Monday over-here!) have used or heard the term. >> Some would argue for a rule related to efficiency of execution. When you >> have multiple blocks as in an if-else or case statement with multiple >> choices, that you order the most common cases first. Those shorten >> execution more often than the rarer cases especially the ones that should >> never happen. > > Those of us who started programming on 8 bit homecomputers of course > have efficiency always at the back of their heads, but I find this ... for mainframes just as much as micro-computers! Regarding execution-efficiencies, I'm sure @Avi knows better than I: It seems likely that Python, as an interpreted language, will create 'blocks' of its virtual-machine code in the same order as they appear in the Python-source. However, aren't there optimising compilers which do something intelligent with the equivalent clauses/suites in other languages? Regardless, is a Jump-instruction which transfers else-control to a block five machine-instructions 'down', any less efficient than a jump which spans 50-instructions? >> So not a rule but realistically not always a bad idea to write code in a >> way that draws the attention of readers along the main path of execution >> and perhaps not showing all the checking for odd cases first. > > much more important. Putting the main path first makes it easier to > understand what the code is supposed to do normally. All those pesky > exceptions are in the "small print" below. Absolutely! Has the term "readability" been used 'here'? Human nature (or is it that of computer programmers in-particular) is to be optimistic: it will work [this time*]. Accordingly, a colleague talks of always coding 'the happy line' first (meaning line of logic, cf source-code). Contrarily, for while-True (infinite) loops, and particularly recursive algorithms, the [wise] counsel is to code the end-condition first. (always know your closest exit! "The nearest exit may be behind you"...) Indeed, dare I say, this optimistic-approach is pythonic. Taking an over-simple, two-value division example, the approach is: try: a = b / c except ZeroDivisionError: ... clean-up the mess ... which contrasts the EAFP philosophy of Python versus the LBYL expectation of (many) other languages: assert c != 0 a = b / c That said, as "Data Science" use of Python expands, it is bringing more and more needs for an LBYL attitude, eg "data cleaning". (EAFP, LBYL? https://docs.python.org/3.9/glossary.html) > There is of course the opposite view that you should just get all of the > confounding factors out of the way first, so that the default is also > the common case. I also do that sometimes, but then I don't hide this in > in an else: clause but do something like this: > > for item in whatever: > if not_this_one(item): > continue > if neither_this_one(item): > continue > if cant_continue(item): > break > if oopsie(): > raise SomeError() > > do_something_with(item) > and_some_more(item) > we_are_done(item) > > which shows visually what the main purpose of the loop (or function or > other block) is. Nicely stated! NB I've seen sufficient of @Peter's posts to know that this was never (even implied to be) intended as a snippet for all occasions! It also illustrates why such is less readable: because we have to scan four if-statements before we can 'see' the purpose of the loop. My 'itch' would be to extract this code 'out' to a function - that way the name will convey the somewhat-obscured purpose of the loop. Alternately, reduce the 'distractions':- try: for item in whatever: inspect_the_data( item ) do_something_with(item) and_some_more(item) we_are_done(item) except SomeError: ... except CustomBreakException: ... ?pass? # same effect as break by 'hiding' in: def inspect_the_data( item ): if not_this_one(item): continue if neither_this_one(item): continue if cant_continue(item): raise CustomBreakException # was break if oopsie(): raise SomeError() It is now easier to understand 'the happy line', ie the thinking of the original-coder, and the 'small print' has been relegated to such and can be cheerfully disregarded. Whereas, if 'exceptional circumstances' is the reason one is inspecting the code in the first-place, then it also helps to have separated-out the ifs-buts-and-maybes, and into a structure which can be as closely (and exhaustively) tested, as may be required. In some ways, (IMHO) there are reasons to feel disquiet over this style of coding. Learning "Modular Programming", and slightly-later "Structured Programming", when they were still new (?fresh, ?exciting), we were inculcated with the 'one way in, one way out' philosophy-of-correctness. This applied to "blocks" of code (per "module"), as well as formal units, eg functions. Accordingly, am slightly unnerved by seeing Exceptions being used to 'jump out' of interior/nested blocks, rather than using the return-mechanism (taking their turn like all the good little boys and girls). That said, it makes for tidier code - so I'll stop muttering into my (grey) beard ... The alternative, assuming the 'errors and omissions' function is a possible tactic(!), would be to return a boolean, eg def is_clean_data( item )->bool: is_verified = False if ... ... return is_verified - thus the do-stuff calls will become a 'successful' if-then 'suite'. There is more code to write/read - and the toy-example lends itself to such a tactic. In other situations, perhaps some refactoring or pre-processing, even a decorator, might remove (or reduce) the need for so much checking within the loop/block. When to use one or the other approach? We could hide behind some 'mystery', and say "I just know from experience", but that smacks of a secret coin-toss (human 'gut feelings' not being particularly indicative of success). So, here's a stab at it which harks back to the learn/use 'COBOL or FORTRAN' [argument] days: If the purpose/considerations of the for-loop (block), are:- - data-related: check-first (and thus consider extract and/or invert to promote readability) - logic/algorithmic implementation, take 'the happy line' first (and deal with the exceptions ("small print") later) Worthy of consideration, is that Python is (still) fast-developing. The switch-case construct of v3.10, and protocols and beefed-up descriptors (?interfaces?) could have quite an impact on such thinking, and in the relatively near-future... * back in the ?bad old days when testing was something that was (only) done AFTER coding was complete, ie ego-driven development. The traditional response to the question: "are you coming to lunch/dinner/supper/break/the party/bed/...?" was "in a moment - [surely?] there's only one more bug"! I've been 'dipping into' Martin Fowler's "Refactoring", 2e, Pearson, 2019; but don't have it with me to point to useful references. What I do have to-hand, because it has just arrived, is Mariano Anaya's "Clean Code in Python", (also 2e), Packt, 2020* - although I didn't see its previous edition, and have read nothing beyond the Contents(!) to-date; it talks of "Design by Contract", "Defensive Programming", "Separation of Concerns" indicating it may have thinking to offer. * the reviewer was Tarek Ziad?, author of "Expert Python", which is worth reading - as are his other works (in English and in French) -- Regards, =dn From python at mrabarnett.plus.com Sun Oct 9 20:47:34 2022 From: python at mrabarnett.plus.com (MRAB) Date: Mon, 10 Oct 2022 01:47:34 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: On 2022-10-10 00:40, dn wrote: > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list > wrote: > >> "shortest block first" > > Have never heard this advice before. Kind-of rankled with me, as it did > for others. > > Enquiring minds want to know... Played Duck, duck, go on this: zero hits > amongst a pile of similar phrases - turns-out there's an algorithm with > a similar name, but not related, and an electronics approach (way too > 'low' a level for translation to us though). > > Tried prefixing with "program" but no such advice to programmers or > program[me] designers. > > Tried prefixing with "python", but equal lack of joy. > > Would OP please quote source? > [snip] After a few minutes searching I found this: https://docs.typo3.org/m/typo3/reference-coreapi/9.5/en-us/CodingGuidelines/CglPhp/PhpFileFormatting/PhpSyntaxFormatting.html """It is recommended to create conditions so that the shortest block of code goes first.""" From list1 at tompassin.net Sun Oct 9 21:13:16 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sun, 9 Oct 2022 21:13:16 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <20221009172932.4wud7mixboy6rvhl@hjp.at> References: <20221009161718.n5fokglnkw3nslnk@hjp.at> <20221009172932.4wud7mixboy6rvhl@hjp.at> Message-ID: On 10/9/2022 1:29 PM, Peter J. Holzer wrote: > On 2022-10-09 12:59:09 -0400, Thomas Passin wrote: >> https://stackoverflow.com/questions/4284313/how-can-i-check-the-syntax-of-python-script-without-executing-it >> >> People seemed especially enthusiastic about the one-liner from jmd_dk. > > I don't think that one-liner solves Antoon's requirement of continuing > after an error. It uses just the normal python parser so it has exactly > the same limitations. Yes, of course. Interesting, though. py_compile tends to be what I use for a quick check. I linked to the page mostly for the other possibilities, as you mentioned below: > Some of the mentioned tools may do what Antoon wants, though. > > hp > > From PythonList at DancesWithMice.info Sun Oct 9 21:19:37 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 10 Oct 2022 14:19:37 +1300 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: <49f6465a-8f0b-05d3-48e4-16a36d9ba5fe@DancesWithMice.info> On 10/10/2022 13.47, MRAB wrote: > On 2022-10-10 00:40, dn wrote: >> On Sun, 9 Oct 2022 at 15:39, Axy via Python-list >> wrote: >> >>> "shortest block first" >> >> Have never heard this advice before. Kind-of rankled with me, as it did >> for others. >> >> Enquiring minds want to know... Played Duck, duck, go on this: zero hits >> amongst a pile of similar phrases - turns-out there's an algorithm with >> a similar name, but not related, and an electronics approach (way too >> 'low' a level for translation to us though). >> >> Tried prefixing with "program" but no such advice to programmers or >> program[me] designers. >> >> Tried prefixing with "python", but equal lack of joy. >> >> Would OP please quote source? >> > [snip] > After a few minutes searching I found this: > > https://docs.typo3.org/m/typo3/reference-coreapi/9.5/en-us/CodingGuidelines/CglPhp/PhpFileFormatting/PhpSyntaxFormatting.html > > """It is recommended to create conditions so that the shortest block of > code goes first.""" Thanks for this! So, a Domain-Specific Language for a CMS. If this is only reference, then hardly a tenet of ComSc thinking or programming-languages! For fun: Typo3 is based on PHP. Advice (apparently) not replicated in PHP-docs (if, else, etc). -- Regards, =dn From rosuav at gmail.com Sun Oct 9 21:23:30 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 12:23:30 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: On Mon, 10 Oct 2022 at 11:52, MRAB wrote: > > On 2022-10-10 00:40, dn wrote: > > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list > > wrote: > > > >> "shortest block first" > > > > Have never heard this advice before. Kind-of rankled with me, as it did > > for others. > > > > Enquiring minds want to know... Played Duck, duck, go on this: zero hits > > amongst a pile of similar phrases - turns-out there's an algorithm with > > a similar name, but not related, and an electronics approach (way too > > 'low' a level for translation to us though). > > > > Tried prefixing with "program" but no such advice to programmers or > > program[me] designers. > > > > Tried prefixing with "python", but equal lack of joy. > > > > Would OP please quote source? > > > [snip] > After a few minutes searching I found this: > > https://docs.typo3.org/m/typo3/reference-coreapi/9.5/en-us/CodingGuidelines/CglPhp/PhpFileFormatting/PhpSyntaxFormatting.html > > """It is recommended to create conditions so that the shortest block of > code goes first.""" Which is more disparaging: "I couldn't find anyone suggesting this" or "The only place I could find it was a PHP style guide"? ChrisA From avi.e.gross at gmail.com Sun Oct 9 22:38:28 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sun, 9 Oct 2022 22:38:28 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <20221009200227.dzmu2thwcsunees3@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> Message-ID: <005101d8dc51$6181ae20$24850a60$@gmail.com> [This is an answer for Peter and can easily be skipped by those who know or have no wish to.] Strictly speaking Peter, the word "pipe" may not mean quite something in Python but other concepts like chaining may be better. The original use of the word I am used to was at the UNIX shell level where an in-core data structure called a pipe was used to connect the output of one process to the inputr of another, sometimes in long chains like: cat file1 file2 file3 | grep pattern | ... | lp Various utilities were thus linked to dynamically create all kinds of solutions. Note the programs ran in parallel and if a program wrote too much into a pipe, it was frozen till the program reading from the pipe caught up a bit and vice versa. So it often ran a lot faster than earlier programs that ran sequentially and each one wrote output (unbuffered) into a file and the next program would read from the file. And, of course, there were no files to clean up and it skipped expensive I/O to and from slow hard disks. Languages like R had extensions added in various ways within a process that were very different. The parts ran sequentially but instead of writing: Name1 <- func1(args) Name2 <- func2(Name1, args) rm(Name1) Name3 <- func3(Name2, args) rm(Name2) ... You could use an add-on library called dplyr (or others) to do something like this where to some extent it is syntactic sugar: Result <- Mydata %>% func1(remaining_args) %>% func2(remaining-args) %>% func3(remaining-args) A practical example would often be written like this using a dta.frame called Mydata that has rows and columns: Mydata <- Mydata %>% select(columns-to-keep) %>% rename(columns-to-change) %>% filter(conditions-on-which-rows-to-keep) %>% mutate(newcol=calculation, newcol=calculation, ...) %>% group_by(column, column, ...) %>% summarize(...) %>% arrange(col, desc(col), ...) %>% ggplot(...) + ... There are many verbs that take your data one step at a time and keep transforming it. The output of each step becomes the hidden first argument of the next step. Not the same kind of pipeline. R recently added a native pipe character so you might use the |> symbol now. It is not quite the same but often faster. So finally getting to how Python (and JavaScript and many others) do something vaguely similar in the sense of chaining. If you have an object with some method you can call on it (or in some cases a normal function call) that returns another (or the same) object, then you can write code like: This.that.other One obvious example that is trivial is an object that contains another object which contains yet another object with attributes. Saying a.b.c.attribute is not really a pipeline but simply multiple lines of code collapsed into one fairly logical bundle. Similarly you can do a.method().method().method() where each method is called on whatever object the preceding method returned which is something "this" in whatever language. The pandas module is designed to make such pipelines doable as many methods return the object being worked on. But consider an example in base Python like a text object that has a method to format as in : "My name is {fname}, I'm {age}".format(fname = "John", age = 36) The result is another string which can then be trimmed or split into parts placed in a list and the list can be asked to do something like throw away the 4th item or remove duplicates or be sorted and several more steps like that using a period to apply some functionality to the current state of the current object. For those who use the python sklearn module, it has a vaguely different idea of a pipeline as in specifying a set of transformations to be done so the result of each step is passed as the input of the next step. You don't do the steps yourself, as much as pass a set of functions to an object that stores them until you ask it to perform an evaluation and then it processed your data using those chained functions which can dynamically change. Lots of machine learning algorithms use similar ideas such as neural networks that propagate data/impulses along a chain of filters and so on. For anyone still reading, the original point must be restated. My point was some people like to program in small byte-size units as if still writing their first BASIC program. When I use a pythonic idiom (or in R or other languages whatever they consider a good way to use the language) they want it dumbed down into simple single lines even in code like: a, b = b, a They would rather use: temp = a a = b b = temp You get the idea. So I have had some nice compact code re-arranged to be much larger and sometimes harder to read and follow. So advice on a goal to make the early blocks of code smaller than later ones may not work when someone changes your code to their wishes! End of digression. Again, not all meanings of pipeline are even close to being the same. -----Original Message----- From: Python-list On Behalf Of Peter J. Holzer Sent: Sunday, October 9, 2022 4:02 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? On 2022-10-09 15:32:13 -0400, Avi Gross wrote: > and of course no pipelines. Since you've now used that term repeatedly: What is a pipeline in Python? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" From avi.e.gross at gmail.com Sun Oct 9 23:19:00 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sun, 9 Oct 2022 23:19:00 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: <00a301d8dc57$0ae19110$20a4b330$@gmail.com> I won't reply to everything Dave says and especially not the parts I fully agree with. I think in many situations in life there is no ONE way to do things so most advice is heuristic at best and many exceptions may exist depending on your chosen approach. As such, I do not really think in PYTHON when writing code but an amalgam of many languages with all kinds of ways of doing things and then zoom in on how to do it in the current language be it Python or R or JavaScript and so on. Yes, I am in some sense focused but also open, just as in Human languages I may mostly be thinking in English but also sometimes see words and phrases pop into my mind from other languages that mean about the same thing and then filter it out to focus on whichever language I am supposed to be using at the time. So back to the topic we are wandering in of what kinds of advice might apply in some complex nested IF-THEN-ELSE structures or CASE statements and so on such as comprehensions as to what ways produce better results much of the time and when another method is better. Someone suggested a method they use that others wondered about. But they have a point. If you make code with large blocks that do not fit on your screen, and indentation is your guide, you can easily lose sight of things. But my advice given glibly is also not serious. Sometimes you may think you are being efficient and as DN pointed out, you are not. The compiler or other software may internally rearrange and optimize your code and make your method not necessary or even prevent the optimization. Your tradeoff may make a program run faster but use more memory or other resources or make it hard for anyone else (or yourself next week) to understand your code or be able to modify it. So, yes, sometimes it is more natural to write code like if score greater than 90, give an A else if greater than 80 give a B, ... else if less than 65, give an F. Perhaps in Harvard your choice of grades is limited to mostly an A and a few B, no C/D as anything lower is an F. Some other school may have few A and mainly C. It may be optimal to start with if between 70 and 80, give a C, then deal with lesser cases. Sometimes the data drives what is more common and hence more efficient. But a big exception is cases where the program blows up if you are not careful. You cannot do certain thinks if a value is empty or NULL or an index above the length of something indexable or trying to write to something read-only and many more. So much code may look like, in pseudocode: Case is.na(var) do this var > length do that value[var] of type integer do whatever ... It may take several steps to make sure your data won't cause an exception if queried without checking if the query makes sense. Only once that is away, might you be able to try for the most common cases for valid data first. Again, as DN points out, in Python some may use exceptions that would jump in for the hopefully rare cases the above type of code tries to protect against. That can be a good approach if these cases are rare and identifiable as unique exceptions so your code focuses on optimizing the good cases you normally expect and shows them up-front with exception-handling code dangling beneath. I suspect some of us prefer some methods over others but can also be ambidextrous as needed. Older languages rapidly killed any program that tried to divide by zero so every single division needed to be protected if a zero might be involved. Mind you, newer languages can face serious bugs with things not easily trapped as value like Inf or NaN or missing values of various kinds can propagate and ruin lots of data. What is the mean of a group of numbers that includes an infinite one? What about some form of NA? Languages like R offer lots of idioms such as having many functions add a codicil like na.rm=TRUE that strips them before they infect your data, but that is not always appropriate. I do not see most programming as a one-size-fits-all approach. Most advice is best ignored. Anyone who suggests that all functions be say no more than 5 lines and that you should waste lots of time and energy making ever more small functions to decompose any larger one till it is under 5 lines but now calls lots of meaningless short functions sometimes 10 levels deep, is not helping you. Goals are fine when they make sense but often the opposite is true. Consider some kind of case statement that has dozens of cases like asking what to do when one of many keys is pressed on a keyboard. The function can be dozens or hundreds of lines long. I could create a function that tests for 'A' and non-A and in the latter case calls a second function that tests for B and non-B and so on. If the user types Z, it is handled in the 26th function! But worse, you may need to pass all kinds of other variables down this chain so whatever key is pressed can do things with local variables. This does not sound like an improvement over one longer function. But yet, sometimes not. You might decide a good way to handle this is to use a dictionary containing all possible keys as keys and varying small functions as arguments. This could make your main function fairly small, once the dictionary had been created using many long lines. So you might say that when evaluating multiple possible solutions, one of several guiding mechanisms is to use fairly short functions. But adding may guiding principles opens up the door for many conflicts so add one saying that if your manager or reviewers insist you do it a specific way, forget the rest unless you do not value your job! Anyone who has read this far, you have my sympathies. LOL! Like me, I suggest you (and I) get a life! In life, there often are no unique right answers albeit an infinite number of wrong answers. -----Original Message----- From: Python-list On Behalf Of dn Sent: Sunday, October 9, 2022 7:41 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? On Sun, 9 Oct 2022 at 15:39, Axy via Python-list wrote: > "shortest block first" Have never heard this advice before. Kind-of rankled with me, as it did for others. Enquiring minds want to know... Played Duck, duck, go on this: zero hits amongst a pile of similar phrases - turns-out there's an algorithm with a similar name, but not related, and an electronics approach (way too 'low' a level for translation to us though). Tried prefixing with "program" but no such advice to programmers or program[me] designers. Tried prefixing with "python", but equal lack of joy. Would OP please quote source? On 10/10/2022 05.56, Peter J. Holzer wrote: > On 2022-10-09 12:18:09 -0400, Avi Gross wrote: >> Smallest code blocks first may be a more modern invention. None of the recent-grads or new-hires I've asked this morning (it's already Monday over-here!) have used or heard the term. >> Some would argue for a rule related to efficiency of execution. When you >> have multiple blocks as in an if-else or case statement with multiple >> choices, that you order the most common cases first. Those shorten >> execution more often than the rarer cases especially the ones that should >> never happen. > > Those of us who started programming on 8 bit homecomputers of course > have efficiency always at the back of their heads, but I find this ... for mainframes just as much as micro-computers! Regarding execution-efficiencies, I'm sure @Avi knows better than I: It seems likely that Python, as an interpreted language, will create 'blocks' of its virtual-machine code in the same order as they appear in the Python-source. However, aren't there optimising compilers which do something intelligent with the equivalent clauses/suites in other languages? Regardless, is a Jump-instruction which transfers else-control to a block five machine-instructions 'down', any less efficient than a jump which spans 50-instructions? >> So not a rule but realistically not always a bad idea to write code in a >> way that draws the attention of readers along the main path of execution >> and perhaps not showing all the checking for odd cases first. > > much more important. Putting the main path first makes it easier to > understand what the code is supposed to do normally. All those pesky > exceptions are in the "small print" below. Absolutely! Has the term "readability" been used 'here'? Human nature (or is it that of computer programmers in-particular) is to be optimistic: it will work [this time*]. Accordingly, a colleague talks of always coding 'the happy line' first (meaning line of logic, cf source-code). Contrarily, for while-True (infinite) loops, and particularly recursive algorithms, the [wise] counsel is to code the end-condition first. (always know your closest exit! "The nearest exit may be behind you"...) Indeed, dare I say, this optimistic-approach is pythonic. Taking an over-simple, two-value division example, the approach is: try: a = b / c except ZeroDivisionError: ... clean-up the mess ... which contrasts the EAFP philosophy of Python versus the LBYL expectation of (many) other languages: assert c != 0 a = b / c That said, as "Data Science" use of Python expands, it is bringing more and more needs for an LBYL attitude, eg "data cleaning". (EAFP, LBYL? https://docs.python.org/3.9/glossary.html) > There is of course the opposite view that you should just get all of the > confounding factors out of the way first, so that the default is also > the common case. I also do that sometimes, but then I don't hide this in > in an else: clause but do something like this: > > for item in whatever: > if not_this_one(item): > continue > if neither_this_one(item): > continue > if cant_continue(item): > break > if oopsie(): > raise SomeError() > > do_something_with(item) > and_some_more(item) > we_are_done(item) > > which shows visually what the main purpose of the loop (or function or > other block) is. Nicely stated! NB I've seen sufficient of @Peter's posts to know that this was never (even implied to be) intended as a snippet for all occasions! It also illustrates why such is less readable: because we have to scan four if-statements before we can 'see' the purpose of the loop. My 'itch' would be to extract this code 'out' to a function - that way the name will convey the somewhat-obscured purpose of the loop. Alternately, reduce the 'distractions':- try: for item in whatever: inspect_the_data( item ) do_something_with(item) and_some_more(item) we_are_done(item) except SomeError: ... except CustomBreakException: ... ?pass? # same effect as break by 'hiding' in: def inspect_the_data( item ): if not_this_one(item): continue if neither_this_one(item): continue if cant_continue(item): raise CustomBreakException # was break if oopsie(): raise SomeError() It is now easier to understand 'the happy line', ie the thinking of the original-coder, and the 'small print' has been relegated to such and can be cheerfully disregarded. Whereas, if 'exceptional circumstances' is the reason one is inspecting the code in the first-place, then it also helps to have separated-out the ifs-buts-and-maybes, and into a structure which can be as closely (and exhaustively) tested, as may be required. In some ways, (IMHO) there are reasons to feel disquiet over this style of coding. Learning "Modular Programming", and slightly-later "Structured Programming", when they were still new (?fresh, ?exciting), we were inculcated with the 'one way in, one way out' philosophy-of-correctness. This applied to "blocks" of code (per "module"), as well as formal units, eg functions. Accordingly, am slightly unnerved by seeing Exceptions being used to 'jump out' of interior/nested blocks, rather than using the return-mechanism (taking their turn like all the good little boys and girls). That said, it makes for tidier code - so I'll stop muttering into my (grey) beard ... The alternative, assuming the 'errors and omissions' function is a possible tactic(!), would be to return a boolean, eg def is_clean_data( item )->bool: is_verified = False if ... ... return is_verified - thus the do-stuff calls will become a 'successful' if-then 'suite'. There is more code to write/read - and the toy-example lends itself to such a tactic. In other situations, perhaps some refactoring or pre-processing, even a decorator, might remove (or reduce) the need for so much checking within the loop/block. When to use one or the other approach? We could hide behind some 'mystery', and say "I just know from experience", but that smacks of a secret coin-toss (human 'gut feelings' not being particularly indicative of success). So, here's a stab at it which harks back to the learn/use 'COBOL or FORTRAN' [argument] days: If the purpose/considerations of the for-loop (block), are:- - data-related: check-first (and thus consider extract and/or invert to promote readability) - logic/algorithmic implementation, take 'the happy line' first (and deal with the exceptions ("small print") later) Worthy of consideration, is that Python is (still) fast-developing. The switch-case construct of v3.10, and protocols and beefed-up descriptors (?interfaces?) could have quite an impact on such thinking, and in the relatively near-future... * back in the ?bad old days when testing was something that was (only) done AFTER coding was complete, ie ego-driven development. The traditional response to the question: "are you coming to lunch/dinner/supper/break/the party/bed/...?" was "in a moment - [surely?] there's only one more bug"! I've been 'dipping into' Martin Fowler's "Refactoring", 2e, Pearson, 2019; but don't have it with me to point to useful references. What I do have to-hand, because it has just arrived, is Mariano Anaya's "Clean Code in Python", (also 2e), Packt, 2020* - although I didn't see its previous edition, and have read nothing beyond the Contents(!) to-date; it talks of "Design by Contract", "Defensive Programming", "Separation of Concerns" indicating it may have thinking to offer. * the reviewer was Tarek Ziad?, author of "Expert Python", which is worth reading - as are his other works (in English and in French) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list From avi.e.gross at gmail.com Sun Oct 9 23:57:40 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sun, 9 Oct 2022 23:57:40 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: <00a901d8dc5c$719fce30$54df6a90$@gmail.com> >>>Which is more disparaging: "I couldn't find anyone suggesting this" or "The only place I could find it was a PHP style guide"? >>>ChrisA Chris, If someone says they heard something from their own personal guru, people often do not feel threatened or argue. I often am told nutrition or medical or other advice that I simply ignore especially if it is about exotic herbs to use or weird ideas like homeopathy or that I should use language X because it is the only way to a haven or heaven or whatever. What we had here was someone suggesting their advice was WELL-KNOWN followed by lots of people sputtering about not having heard of it. I actually think the advice would be reasonable in many circumstances as long as it did not conflict with dozens of goals I find more compelling but which vary on a case by case basis such as whether I am prototyping something I will use once, ... I have studied PHP but have never felt a need to use it and arguably the roles it has played are often done commonly by other programs or methods. Some people might say the same for many languages that are going extinct or that have had to change and adapt to keep being relevant. Had the user mention this was advice given regarding programs in the original BASIC or in COBOL or PASCAL or lots of other languages I may have once used but rarely see much point in caring about, it would be no different. But having ONE source is troublesome. I mean most languages used will suggest some form of making some kinds of variable names meaningful within various constraints. The constraints may be that the maximum length is bounded or that it cannot start with a number (or perhaps underscore) or contain some characters. But other advice varies enough that there is no RIGHT or WRONG across languages. I have seen suggestion to use camelCase or use periods or underscores between parts of a variable name. I have seen suggestions to use a unique prefix or suffix to mark all your own variables as a way to minimize the chance of namespace collisions. Some languages suggest or even enforce that some names be all upper case or have an initial uppercase letter while others should be completely lower case. I mean things like function names versus method names versus class names and so on. The more global advice is ADVICE that suggests whatever method you choose, be consistent. If you make class names a certain way, do it as much as possible for all class names and avoid doing the same thing for non-class names. I think quite a few suggestions fall into the category that they are similar or abstractly enough suggested in many programming languages and by many people. There may be a big enough consensus, perhaps with some outliers, that it may be accepted as reasonable advice to not be ignored without good reasons. So in my view, the objection is not about PHP but about uniqueness. If the author of one Python textbook and no others, suggest that your code should declare all imports in alphabetical order then declare all functions in alphabetical order, they can not only safely be ignored, but perhaps not taken seriously as imports sometimes need to be done carefully if something needs something else and if a language needs functions to be defined before another function body calls them, ... I was not questioning that someone had heard this advice somewhere and did not just make it up. Others searching had trouble finding it but that does not prove anything. Someone finally found one example, which is fine and I suspect there may be other examples found if the search was broader. I suspect there are plenty of places that advise that you should write such code so the main things is visible on the current screen and not buried deeply. But some people seem to miss a point we have discussed. The odd clauses like ELSE after a loop (and quite a few variants in similar and different cases) often provide guarantees such as making sure a file opened is closed. If you look at a Python protocol such as WITH, then things implementing it arrange it so under most circumstances other than pulling a power line out of the wall, the darn file gets closed no matter how you exit the area, and other scenarios try to clean things up even as exceptions are being handled. Sometimes not using these constructs and using something you think is identical but looks better to you, can result in unanticipated behavior. Putting items in a finally or other such clause can be meaningful and sometimes makes some things quite explicit and reliable. Are these things out of the way? Yes, but so what? I see things as a whole not as just a single screen shot. If a loop has several optional clauses lie we are discussing and you know they are normally near the end, then look for them where they are. I know some languages, JavaScript being an example, may have things you might consider odd such as promoting some things like function definitions found further in your code to near the top so you can use a function that is not defined till later even without something like a forward declaration used in other languages. A similar feature allows a default to a case-like statement to be placed anywhere but then be effectively moved to the bottom. This means you can make it very visible at or near the top if you want. As I say, languages and idioms vary. What may be easy to make visible in some is hard or not possible to do easily in another. Thus I keep suggesting you consider using things like comments that help spell out the logic up front and perhaps some that comment on which IF or ELSE the current close bracket (or change in indentation) is connected to or say up front that hundreds of lines later at the end of this loop, look for several clauses that are part of the same logic but have to be placed there, and later on comment at that site what these are there for to modify the above loop. Not perfect but sometimes you work with what you have. I am now going to stop replying on this topic as I have said way too much and am not in particular disagreement if we are discussing preferences and ideas. I see TOOLS here, not religion. Use what works or that has to be used for a task but don't take any one thing too seriously. From rosuav at gmail.com Mon Oct 10 00:20:40 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 15:20:40 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <00a901d8dc5c$719fce30$54df6a90$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <00a901d8dc5c$719fce30$54df6a90$@gmail.com> Message-ID: On Mon, 10 Oct 2022 at 14:59, wrote: > > >>>Which is more disparaging: "I couldn't find anyone suggesting this" or > "The only place I could find it was a PHP style guide"? > >>>ChrisA > > Chris, > > If someone says they heard something from their own personal guru, people > often do not feel threatened or argue. I often am told nutrition or medical > or other advice that I simply ignore especially if it is about exotic herbs > to use or weird ideas like homeopathy or that I should use language X > because it is the only way to a haven or heaven or whatever. > > What we had here was someone suggesting their advice was WELL-KNOWN followed > by lots of people sputtering about not having heard of it. I actually think > the advice would be reasonable in many circumstances as long as it did not > conflict with dozens of goals I find more compelling but which vary on a > case by case basis such as whether I am prototyping something I will use > once, ... It's clearly not all that well known (none of us have heard of it, and it's not exactly prominent on the internet), and it seems that most of us disagree that it's even good advice. So, it's not really a good argument against for-else. > I have studied PHP but have never felt a need to use it and arguably the > roles it has played are often done commonly by other programs or methods. That's because PHP is terrible. > So in my view, the objection is not about PHP but about uniqueness. If the > author of one Python textbook and no others, suggest that your code should > declare all imports in alphabetical order then declare all functions in > alphabetical order, they can not only safely be ignored, but perhaps not > taken seriously as imports sometimes need to be done carefully if something > needs something else and if a language needs functions to be defined before > another function body calls them, ... It's not JUST about uniqueness. It's also that nobody but PHP programmers seem to care about it. That's on par with going to an art supplies forum and trying to argue that you should lay out your paints in a specific order, because some kindergarten teacher always does it that way for the kids' fingerpainting sessions. No, actually, that's unfair to fingerpainting kindergarteners. > But some people seem to miss a point we have discussed. The odd clauses like > ELSE after a loop (and quite a few variants in similar and different cases) > often provide guarantees such as making sure a file opened is closed. Citation needed. > Are these things out of the way? Yes, but so what? I see things as a whole > not as just a single screen shot. If a loop has several optional clauses lie > we are discussing and you know they are normally near the end, then look for > them where they are. So what's your point? > I know some languages, JavaScript being an example, may have things you > might consider odd such as promoting some things like function definitions > found further in your code to near the top so you can use a function that is > not defined till later even without something like a forward declaration > used in other languages. I've hardly ever seen good code that actually uses that. And when it did, it usually wasn't deliberate. Most well-written JS code will do the same thing that Python code does, calling things that have already been defined (if not lexically then temporally). No hoisting needed. > I am now going to stop replying on this topic as I have said way too much > and am not in particular disagreement if we are discussing preferences and > ideas. I see TOOLS here, not religion. Use what works or that has to be used > for a task but don't take any one thing too seriously. Yes, I see tools too. And this thread started out with a discussion of the for-else construct, which was disparaged because it violated a rule that nobody here has heard of, few agree with, and has exceptions already. ChrisA From avi.e.gross at gmail.com Mon Oct 10 00:41:28 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 00:41:28 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Message-ID: <00bd01d8dc62$900ebba0$b02c32e0$@gmail.com> Cameron, Your suggestion makes me shudder! Removing all earlier lines of code is often guaranteed to generate errors as variables you are using are not declared or initiated, modules are not imported and so on. Removing just the line or three where the previous error happened would also have a good chance of invalidating something. Someone who really wants to be able to isolate large parts of their code so that an error in once does not compromise lots of remaining code, might build their code in small units on the level of single functions per file and do lots of imports. They can then ask for all the files to be pseudo-compiled to byte-code and that might provide lots of errors to look at in one pass. But asking for a one-file version to find errors and somehow go past them and look for more is more daunting but of course can be done with partial accuracy and usefulness at best. As an analogy, if tolerated, think of a spell-checker on a document that can find oodles of words spelled wrong. Unfortunately, a spell corrector can drive us nuts if it knows little about context. If it sees a word like "reid" should it just change it to "read" or "red" or perhaps "reed" or look to see if the real problem is it is supposed to be unified (no space) with a word before or after? Will it know if the word appears in a context where a language like Latin or French or German or Hungarian is being quoted and perhaps it is spelled right, or if wrong, has other more likely corrections? Now if you add a grammar detector, and it knows you are looking for an adjective or a verb or a noun, it may do better. I use Google translate quite a bit as a tool as I often have to type in various languages and it provides a handy keyboard or lets me check if I used the right grammar especially in languages with silly ideas that objects can have 2 or even three genders. So putting in phrases like "this xyz" can result in language-specific text that tells me if it is masculine or feminine or perhaps neuter. But the reason I mention it is how often it is WRONG. I mean many languages have multiple words that are spelled the same but used and pronounced differently in various contexts. The English word "read" can sound like reed or like red so past tense sounds different as in I read that book last week versus please read it to me now. But some languages such as Hebrew which generally may not show the vowels, can get totally confused in this program as humans often need lots of context to figure out whether the current short word is in a context where it means "you: feminine and singular and is pronounced aht or it is a way of showing what follows is a direct object and loosely means "the" in a redundant way and is pronounced as "eht". Quite a few words have three or more possible ways to pronounce the same letters and without vowel guides need context and sometimes some spreadsheet-like ingenuity as multiple other words are also in limbo and once resolved can impact what other words may now mean. Obviously adding back the vowels makes things clear so people who are used to seeing books written that old way can get hopelessly lost reading a modern newspaper. End of digression, just assume I could have gone on for many pages describing my annoyances at what Google translate does to many other languages that show the imperfections in what is really a great and powerful tool. Well parsing any program in most languages can be equally complex and require lots of context. For example, you can often use the same identifier to be the name of a regular variable or the name of a function and sometimes other things such as the name of a module. They can often be disambiguated in context. Perhaps the same name following by parentheses should be a function call while a name followed by :: or ::: might in that language require it to be the name of a module/package. If followed by [ it might need to be something indexable such as an array or list and so on. So say there is an error in the variable. Can the interpreter or linter figure out what the error is and almost repair it? Can it see a variable name like "alpXha" and note there is no such identifier in the current namespace but there is one called "alpha" that might be the one without the X? But what if what is missing is an open parent or maybe the matching close paren. Does it know if the problem is a bad variable name or a bad function invocation or one of many other possible problems. Code with a random blemish is often not easily figured out. If I type the name of a function without parentheses, it could be an attempt to call the function with no arguments (an error though in many languages) or it could be I want to pass the function itself as n argument in functional programming. But if I have another variable of type array, might it not be parentheses missing but square brackets? The compiler or interpreter often cannot fix it so it often tries to skip forward till it finds something unambiguous that mark the beginning of a new section. That might be something like an unquoted semicolon at the end of a line or a matching close bracket. Depending on such choices, again, varying amounts of the program may be ignored in evaluating what follows. But this is not the same as a human speedreading or daydreaming who misses a bit here and there and just hopes it was not crucial and that what follows probably remains worthy and valid. I have sometimes missed something like a name and then seen pages of pronouns like "she" and eventually give up as no more hints arrive and I have to go back or ask someone lest a big bunch of the text makes no sense to me. Someone is wanting to treat code from a spelling checker perspective and wants all possible mistakes thrown at them at once. As I pointed out, in real life many kinds of context can matter and a really good checker might even consult a personal list of words it has learned you want ignored, like people's names or some abbreviations like LOL. It may even read marked-up text in say HTML or XML or similar formats that is marked with the language they supposedly contain and calls up a spell-checker appropriate for each region. But if they want a really intelligent program that recovers enough from errors to reliably continue, maybe not easy. They have explained and amended that they understand some of these issues and are willing to get lots of false negatives or red herrings and their real goal is to have a chance to detect and maybe fix a few things per round rather than just one. Not a bad wish. Just not a trivial wish to grant and satisfy. -----Original Message----- From: Python-list On Behalf Of Cameron Simpson Sent: Sunday, October 9, 2022 6:45 PM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On 09Oct2022 21:46, Antoon Pardon wrote: >>Is it that onerous to fix one thing and run it again? It was once when >>you handed in punch cards and waited a day or on very busy machines. > >Yes I find it onerous, especially since I have a pipeline with unit >tests and other tools that all have to redo their work each time a bug >is corrected. It is easy to get the syntax right before submitting to such a pipeline. I usually run a linter on my code for serious commits, and I've got a `lint1` alias which basicly runs the short fast flavour of that which does a syntax check and the very fast less thorough lint phase. I say this just to ease your write/run-tests cycle. Regarding your main request, had you considered writing your own wrapper tool? Something which ran something like: python -We:invalid -m py_compile your_python_file.py If there's an error, report it, then make a new file commencing with the next unindented line after the error, with all preceeding lines commented out (to keep the line numbers the same). Then run the check again. Repeat until the file's empty or there are no errors. This doesn't sound very complex. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list From avi.e.gross at gmail.com Mon Oct 10 01:15:34 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 01:15:34 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <00a901d8dc5c$719fce30$54df6a90$@gmail.com> Message-ID: <00d201d8dc67$53905620$fab10260$@gmail.com> Chris, a short(er) answer to your addition below. I did not at first share your perception but maybe do now. If the argument was that ELSE and other constructs like FINALLY or CATCH are horrible because they follow other code and important things should be first, that is a silly argument. Many are at the end precisely because they are not the main code but have a role to play in making sure various conditions are dealt with. What some of us ended up discussing was whether the advice made much sense in a broader context and were reasonable to strive for. Many of us say not as important as many other things, or not important at all. I note some people looked at the way C had a FOR loop with three parts between semicolons up front as syntactic sugar. No doubt clauses like ELSE could in some way be moved around but the result may well violate other sensibilities as that did because it is a rather nonstandard syntax. I have seen languages with CASE or SWITCH statements that fall through and allow some code to be written once and executed for several scenarios. Others loathe the idea and want each case self-contained. There is no one answer everyone likes. Languages are huge experiments for differing ideas. But it is largely IRRELEVANT in that Python already made the decision and for now it is what it is. We had a different argument a while back as to how the word ELSE captured what is happening linguistically and for many here IT DOES NOT. But once you KNOW what it does, and you choose to use it, then it works just as well as any other words because it is what it is. If having an ELSE late disqualifies Python for this person, use another language! Of course, PHP may not be ideal for so many other reasons! -----Original Message----- From: Python-list On Behalf Of Chris Angelico Sent: Monday, October 10, 2022 12:21 AM To: python-list at python.org Subject: Re: for -- else: what was the motivation? On Mon, 10 Oct 2022 at 14:59, wrote: > > >>>Which is more disparaging: "I couldn't find anyone suggesting this" > >>>or > "The only place I could find it was a PHP style guide"? > >>>ChrisA > > Chris, > > If someone says they heard something from their own personal guru, > people often do not feel threatened or argue. I often am told > nutrition or medical or other advice that I simply ignore especially > if it is about exotic herbs to use or weird ideas like homeopathy or > that I should use language X because it is the only way to a haven or heaven or whatever. > > What we had here was someone suggesting their advice was WELL-KNOWN > followed by lots of people sputtering about not having heard of it. I > actually think the advice would be reasonable in many circumstances as > long as it did not conflict with dozens of goals I find more > compelling but which vary on a case by case basis such as whether I am > prototyping something I will use once, ... It's clearly not all that well known (none of us have heard of it, and it's not exactly prominent on the internet), and it seems that most of us disagree that it's even good advice. So, it's not really a good argument against for-else. > I have studied PHP but have never felt a need to use it and arguably > the roles it has played are often done commonly by other programs or methods. That's because PHP is terrible. > So in my view, the objection is not about PHP but about uniqueness. If > the author of one Python textbook and no others, suggest that your > code should declare all imports in alphabetical order then declare all > functions in alphabetical order, they can not only safely be ignored, > but perhaps not taken seriously as imports sometimes need to be done > carefully if something needs something else and if a language needs > functions to be defined before another function body calls them, ... It's not JUST about uniqueness. It's also that nobody but PHP programmers seem to care about it. That's on par with going to an art supplies forum and trying to argue that you should lay out your paints in a specific order, because some kindergarten teacher always does it that way for the kids' fingerpainting sessions. No, actually, that's unfair to fingerpainting kindergarteners. > But some people seem to miss a point we have discussed. The odd > clauses like ELSE after a loop (and quite a few variants in similar > and different cases) often provide guarantees such as making sure a file opened is closed. Citation needed. > Are these things out of the way? Yes, but so what? I see things as a > whole not as just a single screen shot. If a loop has several optional > clauses lie we are discussing and you know they are normally near the > end, then look for them where they are. So what's your point? > I know some languages, JavaScript being an example, may have things > you might consider odd such as promoting some things like function > definitions found further in your code to near the top so you can use > a function that is not defined till later even without something like > a forward declaration used in other languages. I've hardly ever seen good code that actually uses that. And when it did, it usually wasn't deliberate. Most well-written JS code will do the same thing that Python code does, calling things that have already been defined (if not lexically then temporally). No hoisting needed. > I am now going to stop replying on this topic as I have said way too > much and am not in particular disagreement if we are discussing > preferences and ideas. I see TOOLS here, not religion. Use what works > or that has to be used for a task but don't take any one thing too seriously. Yes, I see tools too. And this thread started out with a discussion of the for-else construct, which was disparaged because it violated a rule that nobody here has heard of, few agree with, and has exceptions already. ChrisA -- https://mail.python.org/mailman/listinfo/python-list From cs at cskk.id.au Mon Oct 10 02:33:47 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 10 Oct 2022 17:33:47 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <00bd01d8dc62$900ebba0$b02c32e0$@gmail.com> References: <00bd01d8dc62$900ebba0$b02c32e0$@gmail.com> Message-ID: On 10Oct2022 00:41, avi.e.gross at gmail.com wrote: >Your suggestion makes me shudder! And fair enough too. I don't do this for me, I'm just suggesting an approach which might bring something to Antoon's objective. >Removing all earlier lines of code is often guaranteed to generate errors as >variables you are using are not declared or initiated, modules are not >imported and so on. Antoon's interested in syntax errors. >Removing just the line or three where the previous error happened would also >have a good chance of invalidating something. Doubtless. He accepts that any such resume-the-parse can bring misleading error messages. Antoon is not expecting magic, just getting several complaints instead of just the first syntax error. I must admit I sympathise a bit, as one of my own major irks is command line tools which moan about the first bad option instead of noting it and moving on to complain about other things as well, then quitting after the command line parse. Pure laziness a lot of the time IMO; I've done it myself, but do like to make multiple complaints when it's feasible. Cheers, Cameron Simpson From wlfraed at ix.netcom.com Sat Oct 8 20:43:14 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sat, 08 Oct 2022 20:43:14 -0400 Subject: Polot severa figures inside a for loopin References: <111638526.9646590.1665256944028.JavaMail.zimbra@inpe.br> Message-ID: <9064khp40rt43vladuht5iq85ut5o3qnv4@4ax.com> On Sun, 9 Oct 2022 09:27:55 +1100, Cameron Simpson declaimed the following: > >And what's IDL? Can you provide a URL to it? > Off hand, given the references to plots, and netcdf & 2D specifically... So a nearly different domain of languages... I'd hope the OP is porting IDL constructs (vector/array) to numpy/scipy. But that also opens the question of what plotting package is being used? Matplotlib or something else? -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From jfong at ms4.hinet.net Sat Oct 8 22:33:07 2022 From: jfong at ms4.hinet.net (Jach Feng) Date: Sat, 8 Oct 2022 19:33:07 -0700 (PDT) Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: Axy ? 2022?10?8? ?????11:39:44 [UTC+8] ?????? > Hi there, > > this is rather a philosophical question, but I assume I miss something. > I don't remember I ever used else clause for years I was with python and > my expectation was it executed only if the the main body was never run. > Ha-ha! I was caught by this mental trap. > > So, seriously, why they needed else if the following pieces produce same > result? Does anyone know or remember their motivation? > > Just curious. > > Axy. > > print('--- with else') > > > for i in [1,2,3]: > print(i) > else: > print(4) > > for i in []: > print(i) > else: > print(5) > > print('--- without else') > > for i in [1,2,3]: > print(i) > print(4) > > for i in []: > print(i) > print(5) The else is always coming with the break, not the for. There are [for ...], [for...break...], and[for...break...else], but the [for...else] is insane. --Jach From bowman at montana.com Sun Oct 9 02:45:31 2022 From: bowman at montana.com (rbowman) Date: Sun, 9 Oct 2022 00:45:31 -0600 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: On 10/8/22 22:37, Axy wrote: > Python is awesome because it's semantic is clear for the majority, but > there are places that look odd. In case of "for", "else" looks logically > tied with "for" clause, but actually it is not. It's tied with "break" > statement and I overlooked that even after re-reading the language > reference. If "else" was named like "never_broken_loop" or "nobreak", > the semantic would be perfectly clear. But, what's done is done. It is sort of an overload for else. It does save an explicit test. For example, in C for (i-0; i References: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Message-ID: <0bfe54f8-7349-1448-b2b3-e7e819d279ac@vub.be> Op 10/10/2022 om 00:45 schreef Cameron Simpson: > On 09Oct2022 21:46, Antoon Pardon wrote: >>> Is it that onerous to fix one thing and run it again? It was once >>> when you >>> handed in punch cards and waited a day or on very busy machines. >> >> Yes I find it onerous, especially since I have a pipeline with unit >> tests >> and other tools that all have to redo their work each time a bug is >> corrected. > > It is easy to get the syntax right before submitting to such a > pipeline.? I usually run a linter on my code for serious commits, and > I've got a `lint1` alias which basicly runs the short fast flavour of > that which does a syntax check and the very fast less thorough lint phase. If you have a linter that doesn't quit after the first syntax error, please provide a link. I already tried pylint and it also quits after the first syntax error. -- Antoon Pardon From cs at cskk.id.au Mon Oct 10 04:50:38 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 10 Oct 2022 19:50:38 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <0bfe54f8-7349-1448-b2b3-e7e819d279ac@vub.be> References: <0bfe54f8-7349-1448-b2b3-e7e819d279ac@vub.be> Message-ID: On 10Oct2022 09:04, Antoon Pardon wrote: >>It is easy to get the syntax right before submitting to such a >>pipeline.? I usually run a linter on my code for serious commits, and >>I've got a `lint1` alias which basicly runs the short fast flavour of >>that which does a syntax check and the very fast less thorough lint >>phase. > >If you have a linter that doesn't quit after the first syntax error, >please provide a link. I already tried pylint and it also quits after >the first syntax error. I don't have such a linter. I did outline an approach for you to write one of your own by wrapping an existing parser program. I have a personal "lint" script which runs a few linters. The first check is `py_compile` which quits at the first syntax error. The other linters are not even tried if that fails. I do not know what your editing environment is; I'd have thought that some IDEs should make the first syntax error very obvious and easy to go to, and an obvious indication that the file as a whoe is syntacticly good/bad. If you have such, between them you could fairly easily resolve syntax errors rapidly, perhaps rapidly enough to make up for a stop-at-the-first-fail syntax check. Cheers, Cameron Simpson From Karsten.Hilbert at gmx.net Mon Oct 10 05:44:42 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Mon, 10 Oct 2022 11:44:42 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Am Sun, Oct 09, 2022 at 09:58:14AM +0000 schrieb Stefan Ram: > I often follow this rule. For me, it's about readability. Compare: > > if not open( disk ): > error( "Can't open disk" ) > else: > printf( "now imagine there's some larger block here" ) ... ad infinitum .... Should this not be if not open( disk ): error( "Can't open disk" ) else: do_lots_of_things_with(disk) as for readability ? Or even if not open( disk ): error( "Can't open disk" ) return what_needs_to_be_returned do_lots_of_things_with(disk) The latter version may need some code reorganization, though. Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From axy at declassed.art Mon Oct 10 05:54:44 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 10:54:44 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> On 09/10/2022 03:33, Jach Feng wrote: > Axy ??? 2022???10???8??? ??????? ???????11:39:44 [UTC+8] ?????????????????? >> Hi there, >> >> this is rather a philosophical question, but I assume I miss something. >> I don't remember I ever used else clause for years I was with python and >> my expectation was it executed only if the the main body was never run. >> Ha-ha! I was caught by this mental trap. >> >> So, seriously, why they needed else if the following pieces produce same >> result? Does anyone know or remember their motivation? >> >> Just curious. >> >> Axy. >> >> print('--- with else') >> >> >> for i in [1,2,3]: >> print(i) >> else: >> print(4) >> >> for i in []: >> print(i) >> else: >> print(5) >> >> print('--- without else') >> >> for i in [1,2,3]: >> print(i) >> print(4) >> >> for i in []: >> print(i) >> print(5) > The else is always coming with the break, not the for. However, the compiler does not complain. > There are [for ...], [for...break...], and[for...break...else], That's implied and contradicts Zen of Python, I think. If "else" came with "break" there had to be a strong indication of that, namely indentation, as it takes place for all other statements with their clauses. However, there's no such an explicit connection between "break" and "else". That's the point. Well, sorry for this addition to the discussion which went weird way. I should had to be cautious mentioning particular coding style, that's a totally different subject, actually. Let's close it at last. > but the [for...else] is insane. Not in Python. Axy. From rosuav at gmail.com Mon Oct 10 06:36:15 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 21:36:15 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 20:46, Karsten Hilbert wrote: > > Am Sun, Oct 09, 2022 at 09:58:14AM +0000 schrieb Stefan Ram: > > > I often follow this rule. For me, it's about readability. Compare: > > > > if not open( disk ): > > error( "Can't open disk" ) > > else: > > printf( "now imagine there's some larger block here" ) > ... ad infinitum .... > > Should this not be > > if not open( disk ): > error( "Can't open disk" ) > else: > do_lots_of_things_with(disk) > > as for readability ? > > Or even > > if not open( disk ): > error( "Can't open disk" ) > return what_needs_to_be_returned > > do_lots_of_things_with(disk) > > The latter version may need some code reorganization, though. I definitely prefer the fail-and-bail version (mainly because, as the number of possible failure modes increases, the code complexity increases linearly, whereas with if/else style it will increase quadratically - you have to edit the entire block, and indent it, for each one). But contrasting the original two? A complete wash. There's no readability difference between them. ChrisA From rosuav at gmail.com Mon Oct 10 06:37:33 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 21:37:33 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 20:56, Axy via Python-list wrote: > > > The else is always coming with the break, not the for. > However, the compiler does not complain. > > There are [for ...], [for...break...], and[for...break...else], > > That's implied and contradicts Zen of Python, I think. If "else" came > with "break" there had to be a strong indication of that, namely > indentation, as it takes place for all other statements with their > clauses. However, there's no such an explicit connection between "break" > and "else". That's the point. > > Well, sorry for this addition to the discussion which went weird way. I > should had to be cautious mentioning particular coding style, that's a > totally different subject, actually. Let's close it at last. > > > but the [for...else] is insane. > Not in Python. > Not sure what you mean, but a for-else without a break is quite useless. What exactly ARE you arguing here? The else is associated with the break to the exact extent that one is essential to the other's value. ChrisA From axy at declassed.art Mon Oct 10 06:55:57 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 11:55:57 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> Message-ID: > Not sure what you mean, but a for-else without a break is quite > useless. What exactly ARE you arguing here? > > The else is associated with the break to the exact extent that one is > essential to the other's value. I'm not arguing. That was just for the record, how things are done in Python. Basically, I simply asked a question and got a definite answer and clear understanding shortly, in a few replies. All the rest of this thread looks irrelevant to me, it's about coding style and probably should be continued under a different title, but I'm not interested to participate in it. Axy. From phd at phdru.name Mon Oct 10 06:41:37 2022 From: phd at phdru.name (Oleg Broytman) Date: Mon, 10 Oct 2022 13:41:37 +0300 Subject: Cheetah 3.3.0 Message-ID: Hello! I'm pleased to announce version 3.3.0, the 1st release of branch 3.3 of CheetahTemplate3. What's new in CheetahTemplate3 ============================== The contributors for this release are: N Protokowicz, Enzo Conty, Andrea Mennucci, Saiprasad Kale, odidev, Pierre Ossman. Many thanks! Great move: - PyPI has wrongfully classified project ``Cheetah3`` as "critical". This puts a burden to use 2FA to manage the project at PyPI. To avoid the burden the project is renamed to ``CT3`` at PyPI. There will be no updates for ``Cheetah3``. Sorry for the inconvenience! Minor features: - Use relative imports everywhere. Tests: - Run pure-python ``NameMapper`` tests in a separate process. - Fixed a bug in tests with pure-python ``NameMapper``. - Add Python 3.10 to ``tox.ini``. CI: - Migrated to GitHub Actions. Due to the absent of Python 3.4 at GH Actions tests are not run and wheels are not built. Installation from sources should work. Due to GH Actions lacking old compilers for w32/w64 releases for old Python versions (currently 2.7) are packaged without compiled _namemapper.pyd extension. Cheetah can be used without compiled _namemapper.pyd extension. A pure-python replacement should work; ``Cheetah`` imports it automatically if the compiled extension is not available. - Stop testing at Travis CI. - Stop testing at AppVeyor. What is CheetahTemplate3 ======================== Cheetah3 is a free and open source (MIT) Python template engine. It's a fork of the original CheetahTemplate library. Python 2.7 or 3.4+ is required. Where is CheetahTemplate3 ========================= Site: https://cheetahtemplate.org/ Download: https://pypi.org/project/CT3/3.3.0 News and changes: https://cheetahtemplate.org/news.html StackOverflow: https://stackoverflow.com/questions/tagged/cheetah Mailing lists: https://sourceforge.net/p/cheetahtemplate/mailman/ Development: https://github.com/CheetahTemplate3 Developer Guide: https://cheetahtemplate.org/dev_guide/ Example ======= Install:: $ pip install CT3 # (or even "ct3") Below is a simple example of some Cheetah code, as you can see it's practically Python. You can import, inherit and define methods just like in a regular Python module, since that's what your Cheetah templates are compiled to :) :: #from Cheetah.Template import Template #extends Template #set $people = [{'name' : 'Tom', 'mood' : 'Happy'}, {'name' : 'Dick', 'mood' : 'Sad'}, {'name' : 'Harry', 'mood' : 'Hairy'}] How are you feeling?
    #for $person in $people
  • $person['name'] is $person['mood']
  • #end for
Oleg. -- Oleg Broytman https://phdru.name/ phd at phdru.name Programmers don't die, they just GOSUB without RETURN. From rosuav at gmail.com Mon Oct 10 07:24:15 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 22:24:15 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 21:57, Axy via Python-list wrote: > > > > Not sure what you mean, but a for-else without a break is quite > > useless. What exactly ARE you arguing here? > > > > The else is associated with the break to the exact extent that one is > > essential to the other's value. > > I'm not arguing. That was just for the record, how things are done in > Python. Basically, I simply asked a question and got a definite answer > and clear understanding shortly, in a few replies. All the rest of this > thread looks irrelevant to me, it's about coding style and probably > should be continued under a different title, but I'm not interested to > participate in it. Here's where the "rest of this thread" started: > Actually the reason I never used "else" was the violation of the rule of > beauty "shortest block first". You disparaged a feature on the basis of a style rule that few of us had heard of or agree with. We all agree that coding style is important; none of us would see block length as a reason to avoid using an else clause on a for loop. Your subsequent posts have left me confused as to what you're trying to convey. ChrisA From axy at declassed.art Mon Oct 10 07:36:21 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 12:36:21 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> Message-ID: <4f1551b7-5ff0-813e-413a-3436977e0a91@declassed.art> On 10/10/2022 12:24, Chris Angelico wrote: > On Mon, 10 Oct 2022 at 21:57, Axy via Python-list > wrote: >> >>> Not sure what you mean, but a for-else without a break is quite >>> useless. What exactly ARE you arguing here? >>> >>> The else is associated with the break to the exact extent that one is >>> essential to the other's value. >> I'm not arguing. That was just for the record, how things are done in >> Python. Basically, I simply asked a question and got a definite answer >> and clear understanding shortly, in a few replies. All the rest of this >> thread looks irrelevant to me, it's about coding style and probably >> should be continued under a different title, but I'm not interested to >> participate in it. > Here's where the "rest of this thread" started: > >> Actually the reason I never used "else" was the violation of the rule of >> beauty "shortest block first". > You disparaged a feature on the basis of a style rule that few of us > had heard of or agree with. Oh, I'm really sorry. My apologies. > We all agree that coding style is > important; none of us would see block length as a reason to avoid > using an else clause on a for loop. As I understand from the above there must be a committee that delegates a speaker? Where to read rules? How to participate? There's something beyond this list I'm not aware of yet? Axy. From rosuav at gmail.com Mon Oct 10 07:48:12 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 10 Oct 2022 22:48:12 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <4f1551b7-5ff0-813e-413a-3436977e0a91@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> <4f1551b7-5ff0-813e-413a-3436977e0a91@declassed.art> Message-ID: On Mon, 10 Oct 2022 at 22:37, Axy via Python-list wrote: > > > On 10/10/2022 12:24, Chris Angelico wrote: > > On Mon, 10 Oct 2022 at 21:57, Axy via Python-list > > wrote: > >> > >>> Not sure what you mean, but a for-else without a break is quite > >>> useless. What exactly ARE you arguing here? > >>> > >>> The else is associated with the break to the exact extent that one is > >>> essential to the other's value. > >> I'm not arguing. That was just for the record, how things are done in > >> Python. Basically, I simply asked a question and got a definite answer > >> and clear understanding shortly, in a few replies. All the rest of this > >> thread looks irrelevant to me, it's about coding style and probably > >> should be continued under a different title, but I'm not interested to > >> participate in it. > > Here's where the "rest of this thread" started: > > > >> Actually the reason I never used "else" was the violation of the rule of > >> beauty "shortest block first". > > You disparaged a feature on the basis of a style rule that few of us > > had heard of or agree with. > Oh, I'm really sorry. My apologies. > > We all agree that coding style is > > important; none of us would see block length as a reason to avoid > > using an else clause on a for loop. > > As I understand from the above there must be a committee that delegates > a speaker? Where to read rules? How to participate? There's something > beyond this list I'm not aware of yet? We in this thread. Look at the past replies. ChrisA From grant.b.edwards at gmail.com Mon Oct 10 09:13:44 2022 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Mon, 10 Oct 2022 06:13:44 -0700 (PDT) Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: <63441a88.050a0220.2fd19.ec95@mx.google.com> On 2022-10-10, Chris Angelico wrote: > On Mon, 10 Oct 2022 at 11:52, MRAB wrote: >> >> On 2022-10-10 00:40, dn wrote: >> > On Sun, 9 Oct 2022 at 15:39, Axy via Python-list >> > wrote: >> > >> >> "shortest block first" >> > >> > Have never heard this advice before. Kind-of rankled with me, as it did >> > for others. I've followed that advice for several decades. I find it much easier to read code that's organized that way -- particularly when the difference in block sizes is large (e.g. the first block is one line, and the second is a a hundred). -- Grant From gweatherby at uchc.edu Mon Oct 10 10:13:10 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Mon, 10 Oct 2022 14:13:10 +0000 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: try: open(disk) except: error(?Can?t open disk?) lots of things From: Python-list on behalf of Karsten Hilbert Date: Monday, October 10, 2022 at 5:46 AM To: python-list at python.org Subject: Re: for -- else: what was the motivation? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** Am Sun, Oct 09, 2022 at 09:58:14AM +0000 schrieb Stefan Ram: > I often follow this rule. For me, it's about readability. Compare: > > if not open( disk ): > error( "Can't open disk" ) > else: > printf( "now imagine there's some larger block here" ) ... ad infinitum .... Should this not be if not open( disk ): error( "Can't open disk" ) else: do_lots_of_things_with(disk) as for readability ? Or even if not open( disk ): error( "Can't open disk" ) return what_needs_to_be_returned do_lots_of_things_with(disk) The latter version may need some code reorganization, though. Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nWwvwKC2eetL3YQnTS4jDih5YRZ_ziu4gPuU73R7LDX8-Kq0bXR-h4E_0kJopk-ud2oeAq6NwvykTB40o82ris6pM1aC$ From cspealma at redhat.com Mon Oct 10 10:36:44 2022 From: cspealma at redhat.com (Calvin Spealman) Date: Mon, 10 Oct 2022 10:36:44 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: On Sat, Oct 8, 2022 at 5:35 PM rbowman wrote: > On 10/7/22 21:32, Axy wrote: > > So, seriously, why they needed else if the following pieces produce same > > result? Does anyone know or remember their motivation? > > In real scenarios there would be more logic in the for block that would > meet a condition and break out of the loop. If the condition is never > met, the else block runs. To steal from w3schools: > > > fruits = ["apple", "peach", "cherry"] > for x in fruits: > print(x) > if x == "banana": > break > else: > print("Yes we got no bananas") > I wonder if for/else could have been less confusing if it was referred to as for-break-else and if the else clause was only valid syntax if the for loop actually contained a break statement in the first place. -- CALVIN SPEALMAN SENIOR QUALITY ENGINEER calvin.spealman at redhat.com M: +1.336.210.5107 [image: https://red.ht/sig] TRIED. TESTED. TRUSTED. From gweatherby at uchc.edu Mon Oct 10 10:52:51 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Mon, 10 Oct 2022 14:52:51 +0000 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: Core developer Raymond Hettinger explains the history starting at 15:40 https://www.youtube.com/watch?v=OSGv2VnC0go (which I found on stackoverflow https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops ) TL:DR The ?else? is a historical artificial from the way developers thought during the transition from unstructured (i.e. ?GOTO?) programming to structured programming. Since we all do structured now, it seems odd. From: Python-list on behalf of Calvin Spealman Date: Monday, October 10, 2022 at 10:38 AM To: python-list at python.org Subject: Re: for -- else: what was the motivation? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** On Sat, Oct 8, 2022 at 5:35 PM rbowman wrote: > On 10/7/22 21:32, Axy wrote: > > So, seriously, why they needed else if the following pieces produce same > > result? Does anyone know or remember their motivation? > > In real scenarios there would be more logic in the for block that would > meet a condition and break out of the loop. If the condition is never > met, the else block runs. To steal from w3schools: > > > fruits = ["apple", "peach", "cherry"] > for x in fruits: > print(x) > if x == "banana": > break > else: > print("Yes we got no bananas") > I wonder if for/else could have been less confusing if it was referred to as for-break-else and if the else clause was only valid syntax if the for loop actually contained a break statement in the first place. -- CALVIN SPEALMAN SENIOR QUALITY ENGINEER calvin.spealman at redhat.com M: +1.336.210.5107 [image: https://urldefense.com/v3/__https://red.ht/sig__;!!Cn_UX_p3!lSA-VzlSq_UQvMUO2npcFCxacA2jOlt2ZD6LCiwdfMGpYexlKgYpIgDCxlHPs473PNyH7cww2ufihhXbt2Z5$ ] TRIED. TESTED. TRUSTED. -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!lSA-VzlSq_UQvMUO2npcFCxacA2jOlt2ZD6LCiwdfMGpYexlKgYpIgDCxlHPs473PNyH7cww2ufihnTgBbx-$ From axy at declassed.art Mon Oct 10 11:47:23 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 16:47:23 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> On 10/10/2022 15:52, Weatherby,Gerard wrote: > Core developer Raymond Hettinger explains the history starting at 15:40 https://www.youtube.com/watch?v=OSGv2VnC0go > > (which I found on stackoverflow https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops ) > > TL:DR > The ?else? is a historical artificial from the way developers thought during the transition from unstructured (i.e. ?GOTO?) programming to structured programming. Since we all do structured now, it seems odd. > > > From: Python-list on behalf of Calvin Spealman > Date: Monday, October 10, 2022 at 10:38 AM > To: python-list at python.org > Subject: Re: for -- else: what was the motivation? > *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > > On Sat, Oct 8, 2022 at 5:35 PM rbowman wrote: > >> On 10/7/22 21:32, Axy wrote: >>> So, seriously, why they needed else if the following pieces produce same >>> result? Does anyone know or remember their motivation? >> In real scenarios there would be more logic in the for block that would >> meet a condition and break out of the loop. If the condition is never >> met, the else block runs. To steal from w3schools: >> >> >> fruits = ["apple", "peach", "cherry"] >> for x in fruits: >> print(x) >> if x == "banana": >> break >> else: >> print("Yes we got no bananas") >> > I wonder if for/else could have been less confusing if it was referred to > as for-break-else and if the else clause was only valid syntax if the for > loop actually contained a break statement in the first place. Sounds reasonable. It would be something alike UnboundLocalError when a local variable referenced before assignment. If they won't remove "else" completely in far future, that checking really worths implementing now. Excellent stackoverflow link, thanks! Axy. From axy at declassed.art Mon Oct 10 13:08:39 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 18:08:39 +0100 Subject: for -- else: what was the motivation? In-Reply-To: <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> Message-ID: <51e25265-2b2d-0361-c5e0-18a69db65444@declassed.art> > On 10/10/2022 15:52, Weatherby,Gerard wrote: >> I wonder if for/else could have been less confusing if it was >> referred to >> as for-break-else and if the else clause was only valid syntax if the >> for >> loop actually contained a break statement in the first place. > > Sounds reasonable. It would be something alike UnboundLocalError when > a local variable referenced before assignment. If they won't remove > "else" completely in far future, that checking really worths > implementing now. Actually, I think a warning would be sufficient, as in the following quick prototype. If someone can implement this quickly in CPython, that would be great (last time I hacked it, it was 2.4) Axy. import ast tree = ast.parse(''' # sample code a = 0 for i in 'asd': ??? a += i ??? while x: ??????? pass ??? else: ??????? print('wow') ??? break ??? print(i) else: ??? print(0) ''', mode='exec') def check_ast(node): ??? if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): ??????? if node.orelse and have_no_break(node.body): ??????????? print(f'Warning: the loop at line {node.lineno} has no "break" statement,' ????????????????? f' "else" clause at line {node.orelse[0].lineno} won\'t run') ??? else: ??????? for child in ast.iter_child_nodes(node): ??????????? check_ast(child) def have_no_break(loop_body): ??? for node in loop_body: ??????? if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): ??????????? # nested loop ??????????? check_ast(node) ??????? elif isinstance(node, ast.Break): ??????????? return False ??????? elif isinstance(node, list): ??????????? for child in ast.iter_child_nodes(node): ??????????????? if have_no_break(child) == False: ??????????????????? return False ??? return True for node in tree.body: ??? check_ast(node) From gweatherby at uchc.edu Mon Oct 10 14:25:19 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Mon, 10 Oct 2022 18:25:19 +0000 Subject: for -- else: what was the motivation? In-Reply-To: <51e25265-2b2d-0361-c5e0-18a69db65444@declassed.art> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> <51e25265-2b2d-0361-c5e0-18a69db65444@declassed.art> Message-ID: pylint, at least, provides a warning: fe.py:4:0: W0120: Else clause on loop without a break statement (useless-else-on-loop) sum = 0 for i in range(5): sum += i else: print("Always executes") print(sum) From: Python-list on behalf of Axy via Python-list Date: Monday, October 10, 2022 at 1:10 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > On 10/10/2022 15:52, Weatherby,Gerard wrote: >> I wonder if for/else could have been less confusing if it was >> referred to >> as for-break-else and if the else clause was only valid syntax if the >> for >> loop actually contained a break statement in the first place. > > Sounds reasonable. It would be something alike UnboundLocalError when > a local variable referenced before assignment. If they won't remove > "else" completely in far future, that checking really worths > implementing now. Actually, I think a warning would be sufficient, as in the following quick prototype. If someone can implement this quickly in CPython, that would be great (last time I hacked it, it was 2.4) Axy. import ast tree = ast.parse(''' # sample code a = 0 for i in 'asd': a += i while x: pass else: print('wow') break print(i) else: print(0) ''', mode='exec') def check_ast(node): if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): if node.orelse and have_no_break(node.body): print(f'Warning: the loop at line {node.lineno} has no "break" statement,' f' "else" clause at line {node.orelse[0].lineno} won\'t run') else: for child in ast.iter_child_nodes(node): check_ast(child) def have_no_break(loop_body): for node in loop_body: if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): # nested loop check_ast(node) elif isinstance(node, ast.Break): return False elif isinstance(node, list): for child in ast.iter_child_nodes(node): if have_no_break(child) == False: return False return True for node in tree.body: check_ast(node) -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mlK4jRkfDC_akw-fIqWaMVf707GQsiyvj_sRHTsFnuG4ak5mKWwSavtz4njlBNIu1H0VHrR9gyjuQpxGqZ1dacU1Xw$ From axy at declassed.art Mon Oct 10 14:41:29 2022 From: axy at declassed.art (Axy) Date: Mon, 10 Oct 2022 19:41:29 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> <51e25265-2b2d-0361-c5e0-18a69db65444@declassed.art> Message-ID: <33852ebb-b9f8-6117-1e59-d9e4596dac67@declassed.art> On 10/10/2022 19:25, Weatherby,Gerard wrote: > > pylint, at least, provides a warning: > > fe.py:4:0: W0120: Else clause on loop without a break statement > (useless-else-on-loop) > I'm using flake8, it does not, alas. Axy. From hjp-python at hjp.at Mon Oct 10 15:03:04 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 10 Oct 2022 21:03:04 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> Message-ID: <20221010190304.nm4bppyjmb2jhtmf@hjp.at> On 2022-10-10 12:40:44 +1300, dn wrote: > On 10/10/2022 05.56, Peter J. Holzer wrote: > > On 2022-10-09 12:18:09 -0400, Avi Gross wrote: > > > Some would argue for a rule related to efficiency of execution. When you > > > have multiple blocks as in an if-else or case statement with multiple > > > choices, that you order the most common cases first. Those shorten > > > execution more often than the rarer cases especially the ones that should > > > never happen. > > > > Those of us who started programming on 8 bit homecomputers of course > > have efficiency always at the back of their heads, but I find this > > ... for mainframes just as much as micro-computers! I knew this would be coming :-). > Regarding execution-efficiencies, I'm sure @Avi knows better than I: It > seems likely that Python, as an interpreted language, will create 'blocks' > of its virtual-machine code in the same order as they appear in the > Python-source. However, aren't there optimising compilers which do something > intelligent with the equivalent clauses/suites in other languages? They can certainly move the code around. So something like if a: long block a elif b: long block b else: long block c could be compiled into (pseudo-python): if a: goto label_a elif b: goto label_b long block c goto end label_a: long block a goto end label_b: long block b end: pass If they can prove that it makes no difference they can also change the order of checking conditions: def f(a: int) -> str: if a < 0: return "negative" elif a > 100: return "big" else: return "meh" could be compiled into the equivalent of: def f(a: int) -> str: if a > 100: return "big" elif a < 0: return "negative" else: return "meh" since an int cannot be simultaneously less then 0 and larger than 100. But if the order does matter, as in def f(a: bool, b: bool) -> int: if a: return 1 elif b: return 2 else: return 3 it can't do any transformations which would change the result. (note that this is a point where it's really important what a language does or does not guarantee) > > Regardless, is a Jump-instruction which transfers else-control to a block > five machine-instructions 'down', any less efficient than a jump which spans > 50-instructions? That depends on the CPU. Some CPUs have different jump instructions for different sizes (for example, for a typical risc cpu the instruction and the offset have to fit in a 32 bit word. So you would be limited to direct jumps of plus or minus a few hundred megabytes. For longer jumps you need to load the address into a register and jump indirectly. CISC CPUs with variable length instructions may have finer distinctions.) A very short jump may continue within the same cache line or maybe even on an instruction which has already been decoded. A longer jump may have to load the next instruction from RAM. Or a jump to the beginning of a cache line may be faster than one to the middle. And then of course there is branch prediction ... So lots of variability there. > > There is of course the opposite view that you should just get all of the > > confounding factors out of the way first, so that the default is also > > the common case. I also do that sometimes, but then I don't hide this in > > in an else: clause but do something like this: > > > > for item in whatever: > > if not_this_one(item): > > continue > > if neither_this_one(item): > > continue > > if cant_continue(item): > > break > > if oopsie(): > > raise SomeError() > > > > do_something_with(item) > > and_some_more(item) > > we_are_done(item) > > > > which shows visually what the main purpose of the loop (or function or > > other block) is. > > Nicely stated! > > NB I've seen sufficient of @Peter's posts to know that this was never (even > implied to be) intended as a snippet for all occasions! > > > It also illustrates why such is less readable: because we have to scan four > if-statements before we can 'see' the purpose of the loop. My 'itch' would > be to extract this code 'out' to a function - that way the name will convey > the somewhat-obscured purpose of the loop. > > > Alternately, reduce the 'distractions':- > > try: > for item in whatever: > inspect_the_data( item ) > do_something_with(item) > and_some_more(item) > we_are_done(item) > except SomeError: > ... > except CustomBreakException: > ... ?pass? # same effect as break > > by 'hiding' in: > > def inspect_the_data( item ): > if not_this_one(item): > continue This doesn't work. You can't continue (or break) a loop in a calling function. (I think it works (or used to work) in Perl, but you'll get a warning.) You could raise CustomContinueExcection() and add a ?try ... catch CustomContinueExcection: pass? block in the loop. > In some ways, (IMHO) there are reasons to feel disquiet over this style of > coding. Learning "Modular Programming", and slightly-later "Structured > Programming", when they were still new (?fresh, ?exciting), we were > inculcated with the 'one way in, one way out' philosophy-of-correctness. > This applied to "blocks" of code (per "module"), as well as formal units, eg > functions. Yeah, there is a fine line between using exceptions to hide unnecessary detail and using exceptions to make a program impenetrable. Or maybe it's not a fine line but a wide grey area? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Mon Oct 10 15:14:12 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 10 Oct 2022 21:14:12 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <005101d8dc51$6181ae20$24850a60$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> <005101d8dc51$6181ae20$24850a60$@gmail.com> Message-ID: <20221010191412.bcavskkwf2e3quh3@hjp.at> On 2022-10-09 22:38:28 -0400, avi.e.gross at gmail.com wrote: > [This is an answer for Peter and can easily be skipped by those who know or > have no wish to.] > > Strictly speaking Peter, the word "pipe" may not mean quite something in > Python but other concepts like chaining may be better. > > The original use of the word I am used to was at the UNIX shell level where > an in-core data structure called a pipe was used To paraphrase Mark Twain, the reports of Unix' death have been greatly exaggerated. Unix (or at least its bastard offsprings Linux and OSX) is alive and well and still has pipes. I use them every day. > If you have an object with some method you can call on it (or in some cases > a normal function call) that returns another (or the same) object, then you > can write code like: > > This.that.other Yeah, I thought you might be referring to that. I've just never seen the term "pipeline" for that construct (I think "method chaining" is reasonably common). hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Mon Oct 10 15:32:56 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 10 Oct 2022 21:32:56 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> Message-ID: <20221010193256.o7wa4vy4tmel6c6h@hjp.at> On 2022-10-10 09:23:27 +1100, Chris Angelico wrote: > On Mon, 10 Oct 2022 at 06:50, Antoon Pardon wrote: > > I just want a parser that doesn't give up on encoutering the first syntax > > error. Maybe do some semantic checking like checking the number of parameters. > > That doesn't make sense though. I think you disagree with most compiler authors here. > It's one thing to keep going after finding a non-syntactic error, but > an error of syntax *by definition* makes parsing the rest of the file > dubious. Dubious but still useful. > What would it even *mean* to not give up? Read the blog post on Lezer for some ideas: https://marijnhaverbeke.nl/blog/lezer.html This is in the context of an editor. But the same problem applies to compilers. It's not very important if a compile run only takes a second or so but even then it might be helpful to see several error messages and not only one at a time. It becomes much more important as compile times get longer (as an extreme[1] example, when I worked on a largeish cobol program in the 1980s, compiling the thing took about half an hour. I really wanted to fix *everything* before starting the compiler again.) Marijn isn't the only person who revisited this problem recently[2]. I've read a few other blog posts and papers on that topic at about the same time. hp [1] Yes, there are programs where a full compile takes much longer than that. But you can usually get away with recompiling only a small part, so you don't have to wait that long during normal development. That cobol compiler couldn't do that. [2] "Recently" means "in the last 10 years or so". -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From rosuav at gmail.com Mon Oct 10 17:02:17 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 08:02:17 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <20221010193256.o7wa4vy4tmel6c6h@hjp.at> References: <00893b0c-e367-6fc9-cdae-f0ee42bc16c0@vub.be> <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> <20221010193256.o7wa4vy4tmel6c6h@hjp.at> Message-ID: On Tue, 11 Oct 2022 at 06:34, Peter J. Holzer wrote: > > On 2022-10-10 09:23:27 +1100, Chris Angelico wrote: > > On Mon, 10 Oct 2022 at 06:50, Antoon Pardon wrote: > > > I just want a parser that doesn't give up on encoutering the first syntax > > > error. Maybe do some semantic checking like checking the number of parameters. > > > > That doesn't make sense though. > > I think you disagree with most compiler authors here. > > > It's one thing to keep going after finding a non-syntactic error, but > > an error of syntax *by definition* makes parsing the rest of the file > > dubious. > > Dubious but still useful. There's a huge difference between non-fatal errors and syntactic errors. The OP wants the parser to magically skip over a fundamental syntactic error and still parse everything else correctly. That's never going to work perfectly, and the OP is surprised at this. > > What would it even *mean* to not give up? > > Read the blog post on Lezer for some ideas: > https://marijnhaverbeke.nl/blog/lezer.html > > This is in the context of an editor. Incidentally, that's actually where I would expect to see that kind of feature show up the most - syntax highlighters will often be designed to "carry on, somehow" after a syntax error, even though it often won't make any sense (just look at what happens to your code highlighting when you omit a quote character). It still won't always be any use, but you do see *some* attempt at it. But if the OP would be satisfied with that, I rather doubt that this thread would even have happened. Unless, of course, the OP still lives in the dark ages when no text editor available had any suitable features for code highlighting. ChrisA From avi.e.gross at gmail.com Mon Oct 10 17:11:55 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 17:11:55 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <78bf8485-48be-7c32-e3e7-d326fa9a85cc@declassed.art> <51e25265-2b2d-0361-c5e0-18a69db65444@declassed.art> Message-ID: <005301d8dcec$ed94bc90$c8be35b0$@gmail.com> I just want to get clear on what may be a side issue The suggestion is that a loop with an ELSE clause only makes sense if the user can BREAK out without finishing, right? My first question is whether a warning or even error makes sense if there is no BREAK statement anywhere in the loop but there is another way to break out such as a RETURN statement or perhaps from an error induced that is not caught and then propagates outward? Or is there some mechanism that would still run the ELSE clause in such cases? The second is to note some break statements are potentially never executed such as: if False: break There are actually scenarios where you can remain in a loop to the end and not do anything rather than break, but of course in that case, the ELSE clause running makes little sense to only run if you finish normally unless it can use a shared Boolean variable you used to skip the rest of the loop and use that to decide. That can be done easily enough without the ELSE, I would think. -----Original Message----- From: Python-list On Behalf Of Weatherby,Gerard Sent: Monday, October 10, 2022 2:25 PM To: Axy ; python-list at python.org Subject: Re: for -- else: what was the motivation? pylint, at least, provides a warning: fe.py:4:0: W0120: Else clause on loop without a break statement (useless-else-on-loop) sum = 0 for i in range(5): sum += i else: print("Always executes") print(sum) From: Python-list on behalf of Axy via Python-list Date: Monday, October 10, 2022 at 1:10 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > On 10/10/2022 15:52, Weatherby,Gerard wrote: >> I wonder if for/else could have been less confusing if it was >> referred to as for-break-else and if the else clause was only valid >> syntax if the for loop actually contained a break statement in the >> first place. > > Sounds reasonable. It would be something alike UnboundLocalError when > a local variable referenced before assignment. If they won't remove > "else" completely in far future, that checking really worths > implementing now. Actually, I think a warning would be sufficient, as in the following quick prototype. If someone can implement this quickly in CPython, that would be great (last time I hacked it, it was 2.4) Axy. import ast tree = ast.parse(''' # sample code a = 0 for i in 'asd': a += i while x: pass else: print('wow') break print(i) else: print(0) ''', mode='exec') def check_ast(node): if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): if node.orelse and have_no_break(node.body): print(f'Warning: the loop at line {node.lineno} has no "break" statement,' f' "else" clause at line {node.orelse[0].lineno} won\'t run') else: for child in ast.iter_child_nodes(node): check_ast(child) def have_no_break(loop_body): for node in loop_body: if isinstance(node, (ast.For, ast.AsyncFor, ast.While)): # nested loop check_ast(node) elif isinstance(node, ast.Break): return False elif isinstance(node, list): for child in ast.iter_child_nodes(node): if have_no_break(child) == False: return False return True for node in tree.body: check_ast(node) -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python- list__;!!Cn_UX_p3!mlK4jRkfDC_akw-fIqWaMVf707GQsiyvj_sRHTsFnuG4ak5mKWwSavtz4n jlBNIu1H0VHrR9gyjuQpxGqZ1dacU1Xw$ -- https://mail.python.org/mailman/listinfo/python-list From jfong at ms4.hinet.net Mon Oct 10 06:40:05 2022 From: jfong at ms4.hinet.net (Jach Feng) Date: Mon, 10 Oct 2022 03:40:05 -0700 (PDT) Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <276e5528-0edf-efa2-4994-758604779cd0@declassed.art> Message-ID: <36f1b3d9-88a3-429c-a1fe-b90609f6663dn@googlegroups.com> Axy ? 2022?10?10? ?????5:55:29 [UTC+8] ?????? > On 09/10/2022 03:33, Jach Feng wrote: > > The else is always coming with the break, not the for. > However, the compiler does not complain. Sure, the compiler will not complain even in a IOCCC contest:-) > > but the [for...else] is insane. > Not in Python. The confusion is always in human mind. ---Jach From michael.stemper at gmail.com Mon Oct 10 09:21:41 2022 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Mon, 10 Oct 2022 08:21:41 -0500 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: On 09/10/2022 10.49, Avi Gross wrote: > Anton > > There likely are such programs out there but are there universal agreements > on how to figure out when a new safe zone of code starts where error > testing can begin? > > For example a file full of function definitions might find an error in > function 1 and try to find the end of that function and resume checking the > next function. But what if a function defines local functions within it? > What if the mistake in one line of code could still allow checking the next > line rather than skipping it all? > > My guess is that finding 100 errors might turn out to be misleading. If you > fix just the first, many others would go away. If you spell a variable name > wrong when declaring it, a dozen uses of the right name may cause errors. > Should you fix the first or change all later ones? How does one declare a variable in python? Sometimes it'd be nice to be able to have declarations and any undeclared variable be flagged. When I was writing F77 for a living, I'd (temporarily) put: IMPLICIT CHARACTER*3 at the beginning of a program or subroutine that I was modifying, in order to have any typos flagged. I'd love it if there was something similar that I could do in python. -- Michael F. Stemper 87.3% of all statistics are made up by the person giving them. From jon+usenet at unequivocal.eu Mon Oct 10 11:43:00 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Mon, 10 Oct 2022 15:43:00 -0000 (UTC) Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: On 2022-10-10, Calvin Spealman wrote: > On Sat, Oct 8, 2022 at 5:35 PM rbowman wrote: >> On 10/7/22 21:32, Axy wrote: >> > So, seriously, why they needed else if the following pieces produce same >> > result? Does anyone know or remember their motivation? >> >> In real scenarios there would be more logic in the for block that would >> meet a condition and break out of the loop. If the condition is never >> met, the else block runs. To steal from w3schools: >> >> >> fruits = ["apple", "peach", "cherry"] >> for x in fruits: >> print(x) >> if x == "banana": >> break >> else: >> print("Yes we got no bananas") >> > > I wonder if for/else could have been less confusing if it was referred to > as for-break-else and if the else clause was only valid syntax if the for > loop actually contained a break statement in the first place. Watch out, I suggested that here some years ago and it was derided as being an "arrogant and foolish" idea. From boblatest at yahoo.com Mon Oct 10 12:43:16 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 16:43:16 GMT Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Chris Angelico wrote: > Yes, I'm aware that code readability becomes irrelevant for > short-duration projects. Beside the point. I'm wondering how important > it really is to have the shortest block first. I usually put the most expected / frequent / not negated block first if the whole if/else statement is not "too long". Sometimes whatever you want to do becomes pointless if a certain conditions is not met, in which case I do an early break or return and have no else block at all. > Given that for-else is an excellent, if rarely-used, construct I knew it existed but coming from C I never thought to exploit it. I know I wrote loops like this: found = None while not found: found = search(something) if found: break if not found: complain() Need to look into using "else" in these cases. From boblatest at yahoo.com Mon Oct 10 12:48:04 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 16:48:04 GMT Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: Axy wrote: >> Also not really a justification for "shortest block first". Wanting >> some elaboration on that. What's the value in it? > > Well, the value is productivity. No need to save puzzles "what this > hanging else belongs to?" If you find yourself asking that question, the if-block is probably too long to begin with. > Code small things first and return early, same > as taking a test: do easy and quick things first and boring and > difficult ones later. Yes, but in that case you have a very long indented "else" block, and at the point where the unindent happens you are scratching your head again like before. Better to immediately return or break and not to use any "else" block at all. From boblatest at yahoo.com Mon Oct 10 12:59:27 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 16:59:27 GMT Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <63441a88.050a0220.2fd19.ec95@mx.google.com> Message-ID: Grant Edwards wrote: > I've followed that advice for several decades. I find it much easier > to read code that's organized that way -- particularly when the > difference in block sizes is large (e.g. the first block is one line, > and the second is a a hundred). If any conditionally executed blocks is a hundred lines, I believe your code needs refactoring. I know mine does. Either the long block should go into an extra function, or you do a "fail and bail" (just learned that phrase). From boblatest at yahoo.com Mon Oct 10 13:06:37 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 17:06:37 GMT Subject: What to use for finding as many syntax errors as possible. References: Message-ID: Michael F. Stemper wrote: > How does one declare a variable in python? Sometimes it'd be nice to > be able to have declarations and any undeclared variable be flagged. To my knowledge, the closest to that is using __slots__ in class definitions. Many a time have I assigned to misspelled class members until I discovered __slots__. From boblatest at yahoo.com Mon Oct 10 13:08:32 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 17:08:32 GMT Subject: What to use for finding as many syntax errors as possible. References: Message-ID: Antoon Pardon wrote: > I would like a tool that tries to find as many syntax errors as possible > in a python file. I'm puzzled as to when such a tool would be needed. How many syntax errors can you realistically put into a single Python file before compiling it for the first time? From boblatest at yahoo.com Mon Oct 10 13:14:13 2022 From: boblatest at yahoo.com (Robert Latest) Date: 10 Oct 2022 17:14:13 GMT Subject: What to use for finding as many syntax errors as possible. References: <8ba966ed-a935-84ea-f65d-fec0dc71403a@vub.be> <00bd01d8dc62$900ebba0$b02c32e0$@gmail.com> Message-ID: wrote: > Cameron, > > Your suggestion makes me shudder! Me, too > Removing all earlier lines of code is often guaranteed to generate errors as > variables you are using are not declared or initiated, modules are not > imported and so on. all of which aren't syntax errors, so the method should still work. Ugly as hell though. I can't think of a reason to want to find multiple syntax errors in a file. From michael.stemper at gmail.com Mon Oct 10 14:32:46 2022 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Mon, 10 Oct 2022 13:32:46 -0500 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> Message-ID: On 09/10/2022 15.02, Peter J. Holzer wrote: > On 2022-10-09 15:32:13 -0400, Avi Gross wrote: >> and of course no pipelines. > > Since you've now used that term repeatedly: What is a pipeline in > Python? Could it be what's discussed starting on page 35 of this presentation? -- Michael F. Stemper Life's too important to take seriously. From kevinmwilson1956 at yahoo.com Mon Oct 10 17:48:21 2022 From: kevinmwilson1956 at yahoo.com (Kevin M. Wilson) Date: Mon, 10 Oct 2022 21:48:21 +0000 (UTC) Subject: Help, PyCharm fails to recognize my tab setting...See attached picture of the code. References: <2030144807.7310447.1665438501827.ref@mail.yahoo.com> Message-ID: <2030144807.7310447.1665438501827@mail.yahoo.com> C:\Users\kevin\PycharmProjects\Myfuturevalue\venv\Scripts\python.exe C:\Users\kevin\PycharmProjects\Myfuturevalue\FutureValueCal.py?? File "C:\Users\kevin\PycharmProjects\Myfuturevalue\FutureValueCal.py", line 31? ? elif (years > 50.0) or (years < 1.0) :? ? ^IndentationError: expected an indented block after 'if' statement on line 29 Process finished with exit code 1 Good sense makes one slow to anger, and it is his glory tooverlook an offense. Proverbs 19:11 From rosuav at gmail.com Mon Oct 10 18:00:11 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 09:00:11 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: On Tue, 11 Oct 2022 at 08:55, Robert Latest via Python-list wrote: > > Chris Angelico wrote: > > Yes, I'm aware that code readability becomes irrelevant for > > short-duration projects. Beside the point. I'm wondering how important > > it really is to have the shortest block first. > > I usually put the most expected / frequent / not negated block first if the > whole if/else statement is not "too long". Sometimes whatever you want to do > becomes pointless if a certain conditions is not met, in which case I do an > early break or return and have no else block at all. > > > Given that for-else is an excellent, if rarely-used, construct > > I knew it existed but coming from C I never thought to exploit it. I know I > wrote loops like this: > > found = None > while not found: > found = search(something) > if found: > break > if not found: > complain() > > Need to look into using "else" in these cases. Yep, that's exactly what for-else is great at! while True: if search(something): break else: complain() (although rather than a "while True", you're probably iterating over things to search for, in some way) ChrisA From cs at cskk.id.au Mon Oct 10 18:17:13 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 11 Oct 2022 09:17:13 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: On 11Oct2022 08:02, Chris Angelico wrote: >There's a huge difference between non-fatal errors and syntactic >errors. The OP wants the parser to magically skip over a fundamental >syntactic error and still parse everything else correctly. That's >never going to work perfectly, and the OP is surprised at this. The OP is not surprised by this, and explicitly expressed awareness that resuming a parse had potential for "misparsing" further code. I remain of the opinion that one could resume a parse at the next unindented line and get reasonable results a lot of the time. In fact, I expect that one could resume tokenising at almost any line which didn't seem to be inside a string and often get reasonable results. I grew up with C and Pascal compilers which would _happily_ produce many complaints, usually accurate, and all manner of syntactic errors. They didn't stop at the first syntax error. All you need in principle is a parser which goes "report syntax error here, continue assuming ". For Python that might mean "pretend a missing final colon" or "close open brackets" etc, depending on the context. If you make conservative implied corrections you can get a reasonable continued parse, enough to find further syntax errors. I remember the Pascal compiler in particular had a really good "you missed a semicolon _back there_" mode which was almost always correct, a nice boon when correcting mistakes. Cheers, Cameron Simpson From cs at cskk.id.au Mon Oct 10 18:22:25 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 11 Oct 2022 09:22:25 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: On 09/10/2022 10.49, Avi Gross wrote: >>My guess is that finding 100 errors might turn out to be misleading. >>If you >>fix just the first, many others would go away. If you spell a variable name >>wrong when declaring it, a dozen uses of the right name may cause errors. >>Should you fix the first or change all later ones? Just to this, these are semantic errors, not syntax errors. Linters do an ok job of spotting these. Antoon is after _syntax errors_. On 10Oct2022 08:21, Michael F. Stemper wrote: >How does one declare a variable in python? Sometimes it'd be nice to >be able to have declarations and any undeclared variable be flagged. Linters do pretty well at this. They can trace names and their use compared to their first definition/assignment (often - there are of course some constructs which are correct but unclear to a static analysis - certainly one of my linters occasionally says "possible undefine use" to me because there may be a path to use before set). This is particularly handy for typos, which often make for "use before set" or "set and not used". >I'd love it if there was something similar that I could do in python. Have you used any lint programmes? My "lint" script runs pyflakes and pylint. Cheers, Cameron Simpson From rosuav at gmail.com Mon Oct 10 18:47:52 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 09:47:52 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: On Tue, 11 Oct 2022 at 09:18, Cameron Simpson wrote: > > On 11Oct2022 08:02, Chris Angelico wrote: > >There's a huge difference between non-fatal errors and syntactic > >errors. The OP wants the parser to magically skip over a fundamental > >syntactic error and still parse everything else correctly. That's > >never going to work perfectly, and the OP is surprised at this. > > The OP is not surprised by this, and explicitly expressed awareness that > resuming a parse had potential for "misparsing" further code. > > I remain of the opinion that one could resume a parse at the next > unindented line and get reasonable results a lot of the time. The next line at the same indentation level as the line with the error, or the next flush-left line? Either way, there's a weird and arbitrary gap before you start parsing again, and you still have no indication of what could make sense. Consider: if condition # no colon code else: code To actually "restart" parsing, you have to make a guess of some sort. Maybe you can figure out what the user meant to do, and parse accordingly; but if that's the case, keep going immediately, don't wait for an unindented line. If you want for a blank line followed by an unindented line, that might help with a notion of "next logical unit of code", but it's very much dependent on the coding style, and if you have a codebase that's so full of syntax errors that you actually want to see more than one, you probably don't have a codebase with pristine and beautiful code layout. > In fact, I expect that one could resume tokenising at almost any line > which didn't seem to be inside a string and often get reasonable > results. "Seem to be"? On what basis? > I grew up with C and Pascal compilers which would _happily_ produce many > complaints, usually accurate, and all manner of syntactic errors. They > didn't stop at the first syntax error. Yes, because they work with a much simpler grammar. But even then, most syntactic errors (again, this is not to be confused with semantic errors - if you say "char *x = 1.234;" then there's no parsing ambiguity but it's not going to compile) cause a fair degree of nonsense afterwards. The waters are a bit muddied by some things being called "syntax errors" when they're actually nothing at all to do with the parser. For instance: >>> def f(): ... await q ... File "", line 2 SyntaxError: 'await' outside async function This is not what I'm talking about; there's no parsing ambiguity here, and therefore no difficulty whatsoever in carrying on with the parsing. You could ast.parse() this code without an error. But resuming after a parsing error is fundamentally difficult, impossible without guesswork. > All you need in principle is a parser which goes "report syntax error > here, continue assuming ". For Python that might mean > "pretend a missing final colon" or "close open brackets" etc, depending > on the context. If you make conservative implied corrections you can get > a reasonable continued parse, enough to find further syntax errors. And, more likely, you'll generate a lot of nonsense. Take something like this: items = [ item[1], item2], item[3], ] As a human, you can easily see what the problem is. Try teaching a parser how to handle this. Most likely, you'll generate a spurious error - maybe the indentation, maybe the intended end of the list - but there's really only one error here. Reporting multiple errors isn't actually going to be at all helpful. > I remember the Pascal compiler in particular had a really good "you > missed a semicolon _back there_" mode which was almost always correct, a > nice boon when correcting mistakes. > Ahh yes. Design a language with strict syntactic requirements, and it's not too hard to find where the programmer has omitted them. Thing is.... Python just doesn't HAVE those semicolons. Let's say that a variant Python required you to put a U+251C ? at the start of every statement, and U+2524 ? at the end of the statement. A whole lot of classes of error would be extremely easy to notice and correct, and thus you could resume parsing; but that isn't benefiting the programmer any. When you don't have that kind of information duplication, it's a lot harder to figure out how to cheat the fix and go back to parsing. ChrisA From list1 at tompassin.net Mon Oct 10 18:25:42 2022 From: list1 at tompassin.net (Thomas Passin) Date: Mon, 10 Oct 2022 18:25:42 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <1a7b14b1-5648-89a1-af03-771b9170d37a@tompassin.net> On 10/10/2022 9:21 AM, Michael F. Stemper wrote: > On 09/10/2022 10.49, Avi Gross wrote: >> Anton >> >> There likely are such programs out there but are there universal >> agreements >> on how to figure out when a new safe zone of code starts where error >> testing can begin? >> >> For example a file full of function definitions might find an error in >> function 1 and try to find the end of that function and resume >> checking the >> next function.? But what if a function defines local functions within it? >> What if the mistake in one line of code could still allow checking the >> next >> line rather than skipping it all? >> >> My guess is that finding 100 errors might turn out to be misleading. >> If you >> fix just the first, many others would go away. If you spell a variable >> name >> wrong when declaring it, a dozen uses of the right name may cause errors. >> Should you fix the first or change all later ones? > > How does one declare a variable in python? Sometimes it'd be nice to > be able to have declarations and any undeclared variable be flagged. > > When I was writing F77 for a living, I'd (temporarily) put: > ????? IMPLICIT CHARACTER*3 > at the beginning of a program or subroutine that I was modifying, > in order to have any typos flagged. > > I'd love it if there was something similar that I could do in python. The Leo editor (https://github.com/leo-editor/leo-editor) will notify you of undeclared variables (and some syntax errors) each time you save your (Python) file. From avi.e.gross at gmail.com Mon Oct 10 22:09:06 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 22:09:06 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <008201d8dd16$718fd420$54af7c60$@gmail.com> Michael, A reasonable question. Python lets you initialize variables but has no explicit declarations. Languages differ and I juggle attributes of many in my mind and am reacting to the original question NOT about whether and how Python should report many possible errors all at once but how ANY language can be expected to do this well. Many others do have a variable declaration phase or an optional declaration or perhaps just a need to declare a function prototype so it can be used by others even if the formal function creation will happen later in the code. But what I meant in a Python context was something like this: Wronk = who cares # this should fail ... If (Wronk > 5): ... ... Wronger = Wronk + 1 ... X = minimum(Wronk, Wronger, 12) The first line does not parse well so you have an error. But in any case as the line makes no sense, Wronk is not initialized to anything. Later code may use it in various ways and some of those may be seen as errors for an assortment of reasons, then at one point the code does provide a value for Wronk and suddenly code beyond that has no seeming errors. The above examples are not meant to be real but just give a taste that programs with holes in them for any reason may not be consistent. The only relatively guaranteed test for sanity has to start at the top and encounter no errors or missing parts based on an anything such as I/O errors. And I suggest there are some things sort of declared in python such as: Import numpy as np Yes, that brings in code from a module if it works and initializes a variable called np to sort of point at the module or it's namespace or whatever, depending on the language. It is an assignment but also a way to let the program know things. If the above is: Import grumpy as np Then what happens if the code tries to find a file named "grumpy" somewhere and cannot locate it and this is considered a syntax error rather than a run-time error for whatever reason? Can you continue when all kinds of functionality is missing and code asking to make a np.array([1,2,3]) clearly fails? Many of us here are talking past each other. Yes, it would be nice to get lots of info and arguably we may eventually have machine-learning or AI programs a bit more like SPAM detectors that look for patterns commonly found and try to fix your program from common errors or at least do a temporary patch so they can continue searching for more errors. This could result in the best case in guessing right every time. If you allowed it to actually fix your code, it might be like people who let their spelling be corrected and do not proofread properly and send out something embarrassing or just plain wrong! And it will compile or be interpreted without complaint albeit not do exactly what it is supposed to! -----Original Message----- From: Python-list On Behalf Of Michael F. Stemper Sent: Monday, October 10, 2022 9:22 AM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On 09/10/2022 10.49, Avi Gross wrote: > Anton > > There likely are such programs out there but are there universal > agreements on how to figure out when a new safe zone of code starts > where error testing can begin? > > For example a file full of function definitions might find an error in > function 1 and try to find the end of that function and resume > checking the next function. But what if a function defines local functions within it? > What if the mistake in one line of code could still allow checking the > next line rather than skipping it all? > > My guess is that finding 100 errors might turn out to be misleading. > If you fix just the first, many others would go away. If you spell a > variable name wrong when declaring it, a dozen uses of the right name may cause errors. > Should you fix the first or change all later ones? How does one declare a variable in python? Sometimes it'd be nice to be able to have declarations and any undeclared variable be flagged. When I was writing F77 for a living, I'd (temporarily) put: IMPLICIT CHARACTER*3 at the beginning of a program or subroutine that I was modifying, in order to have any typos flagged. I'd love it if there was something similar that I could do in python. -- Michael F. Stemper 87.3% of all statistics are made up by the person giving them. -- https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Mon Oct 10 22:41:40 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 13:41:40 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <008201d8dd16$718fd420$54af7c60$@gmail.com> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> Message-ID: On Tue, 11 Oct 2022 at 13:10, wrote: > If the above is: > > Import grumpy as np > > Then what happens if the code tries to find a file named "grumpy" somewhere > and cannot locate it and this is considered a syntax error rather than a > run-time error for whatever reason? Can you continue when all kinds of > functionality is missing and code asking to make a np.array([1,2,3]) clearly > fails? That's not a syntax error. Syntax is VERY specific. It is an error in Python to attempt to add 1 to "one", it is an error to attempt to look up the upper() method on None, it is an error to try to use a local variable you haven't assigned to yet, and it is an error to open a file that doesn't exist. But not one of these is a *syntax* error. Syntax errors are detected at the parsing stage, before any code gets run. The vast majority of syntax errors are grammar errors, where the code doesn't align with the parseable text of a Python program. (Non-grammatical parsing errors include using a "nonlocal" statement with a name that isn't found in any surrounding scope, using "await" in a non-async function, and attempting to import braces from the future.) ChrisA From avi.e.gross at gmail.com Mon Oct 10 23:11:33 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 23:11:33 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <00ab01d8dd1f$2af0f9f0$80d2edd0$@gmail.com> Cameron, or OP if you prefer, I think by now you have seen a suggestion that languages make choices and highly structured ones can be easier to "recover" from errors and try to continue than some with way more complex possibilities that look rather unstructured. What is the error in code like this? A,b,c,d = 1,2, Or is it an error at all? Many languages have no concept of doing anything like the above and some tolerate a trailing comma and some set anything not found to some form of NULL or uninitialized and some ... If you look at human language, some are fairly simple and some are way too organized. But in a way it can make sense. Languages with gender will often ask you to change the spelling and often how you pronounce things not only based on whether a noun is male/female or even neuter but also insist you change the form of verbs or adjectives and so on that in effect give multiple signals that all have to line up to make a valid and understandable sentence. Heck, in conversations, people can often leave out parts of a sentence such as whether you are talking about "I" or "you" or "she" or "we" because the rest of the words in the sentence redundantly force only one choice to be possible. So some such annoying grammars (in my opinion) are error detection/correction codes in disguise. In days before microphones and speakers, it was common to not hear people well, like on a stage a hundred feet away with other ambient noises. Missing a word or two might still allow you to get the point as other parts of the sentence did such redundancies. Many languages have similar strictures letting you know multiple times if something is singular or plural. And I think another reason was what I call stranger detection. People who learn some vocabulary might still not speak correctly and be identifiable as strangers, as in spies. Do we need this in the modern age? Who knows! But it makes me prefer some languages over others albeit other reasons may ... With the internet today, we are used to expecting error correction to come for free. Do you really need one of every 8 bits to be a parity bit, which only catches may half of the errors, when the internals of your computer are relatively error free and even the outside is protected by things like various protocols used in making and examining packets and demanding some be sent again if some checksum does not match? Tons of checking is built in so at your level you rarely think about it. If you get a message, it usually is either 99.9999% accurate, or you do not have it shown to you at all. I am not talking about SPAM but about errors of transmission. So my analogies are that if you want a very highly structured language that can recover somewhat from errors, Python may not be it. And over the years as features are added or modified, the structure tends to get more complex. And R is not alone. Many surviving languages continue to evolve and borrow from each other and any program that you run today that could partially recover and produce pages of possible errors, may blow up when new features are introduced. And with UNICODE, the number of possible "errors" in what is placed in code for languages like Julia that allow them in most places ... -----Original Message----- From: Python-list On Behalf Of Cameron Simpson Sent: Monday, October 10, 2022 6:17 PM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On 11Oct2022 08:02, Chris Angelico wrote: >There's a huge difference between non-fatal errors and syntactic >errors. The OP wants the parser to magically skip over a fundamental >syntactic error and still parse everything else correctly. That's never >going to work perfectly, and the OP is surprised at this. The OP is not surprised by this, and explicitly expressed awareness that resuming a parse had potential for "misparsing" further code. I remain of the opinion that one could resume a parse at the next unindented line and get reasonable results a lot of the time. In fact, I expect that one could resume tokenising at almost any line which didn't seem to be inside a string and often get reasonable results. I grew up with C and Pascal compilers which would _happily_ produce many complaints, usually accurate, and all manner of syntactic errors. They didn't stop at the first syntax error. All you need in principle is a parser which goes "report syntax error here, continue assuming ". For Python that might mean "pretend a missing final colon" or "close open brackets" etc, depending on the context. If you make conservative implied corrections you can get a reasonable continued parse, enough to find further syntax errors. I remember the Pascal compiler in particular had a really good "you missed a semicolon _back there_" mode which was almost always correct, a nice boon when correcting mistakes. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list From avi.e.gross at gmail.com Mon Oct 10 23:24:42 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Mon, 10 Oct 2022 23:24:42 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <008201d8dd16$718fd420$54af7c60$@gmail.com> Message-ID: <00b001d8dd21$01475160$03d5f420$@gmail.com> I stand corrected Chris, and others, as I pay the sin tax. Yes, there are many kinds of errors that logically fall into different categories or phases of evaluation of a program and some can be determined by a more static analysis almost on a line by line (or "statement" or "expression", ...) basis and others need to sort of simulate some things and look back and forth to detect possible incompatibilities and yet others can only be detected at run time and likely way more categories depending on the language. But when I run the Python interpreter on code, aren't many such phases done interleaved and at once as various segments of code are parsed and examined and perhaps compiled into block code and eventually executed? So is the OP asking for something other than a Python Interpreter that normally halts after some kind of error? Tools like a linter may indeed fit that mold. This may limit some of the objections of when an error makes it hard for the parser to find some recovery point to continue from as no code is being run and no harmful side effects happen by continuing just an analysis. Time to go read some books about modern ways to evaluate a language based on more mathematical rules including more precisely what is syntax versus ... Suggestions? -----Original Message----- From: Python-list On Behalf Of Chris Angelico Sent: Monday, October 10, 2022 10:42 PM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On Tue, 11 Oct 2022 at 13:10, wrote: > If the above is: > > Import grumpy as np > > Then what happens if the code tries to find a file named "grumpy" > somewhere and cannot locate it and this is considered a syntax error > rather than a run-time error for whatever reason? Can you continue > when all kinds of functionality is missing and code asking to make a > np.array([1,2,3]) clearly fails? That's not a syntax error. Syntax is VERY specific. It is an error in Python to attempt to add 1 to "one", it is an error to attempt to look up the upper() method on None, it is an error to try to use a local variable you haven't assigned to yet, and it is an error to open a file that doesn't exist. But not one of these is a *syntax* error. Syntax errors are detected at the parsing stage, before any code gets run. The vast majority of syntax errors are grammar errors, where the code doesn't align with the parseable text of a Python program. (Non-grammatical parsing errors include using a "nonlocal" statement with a name that isn't found in any surrounding scope, using "await" in a non-async function, and attempting to import braces from the future.) ChrisA -- https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Mon Oct 10 23:24:28 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 14:24:28 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <00ab01d8dd1f$2af0f9f0$80d2edd0$@gmail.com> References: <00ab01d8dd1f$2af0f9f0$80d2edd0$@gmail.com> Message-ID: On Tue, 11 Oct 2022 at 14:13, wrote: > With the internet today, we are used to expecting error correction to come > for free. Do you really need one of every 8 bits to be a parity bit, which > only catches may half of the errors... Fortunately, we have WAY better schemes than simple parity, which was only really a thing in the modem days. (Though I would say that there's still a pretty clear distinction between a good message where everything has correct parity, and line noise where half of them don't.) Hamming codes can correct one-bit errors (and detect two-bit errors) at a price of log2(size)+1 bits of space. Here's a great rundown: https://www.youtube.com/watch?v=X8jsijhllIA There are other schemes too, but Hamming codes are beautifully elegant and easy to understand. ChrisA From rosuav at gmail.com Mon Oct 10 23:55:12 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 14:55:12 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <00b001d8dd21$01475160$03d5f420$@gmail.com> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> Message-ID: On Tue, 11 Oct 2022 at 14:26, wrote: > > I stand corrected Chris, and others, as I pay the sin tax. > > Yes, there are many kinds of errors that logically fall into different > categories or phases of evaluation of a program and some can be determined > by a more static analysis almost on a line by line (or "statement" or > "expression", ...) basis and others need to sort of simulate some things > and look back and forth to detect possible incompatibilities and yet others > can only be detected at run time and likely way more categories depending on > the language. > > But when I run the Python interpreter on code, aren't many such phases done > interleaved and at once as various segments of code are parsed and examined > and perhaps compiled into block code and eventually executed? Hmm, depends what you mean. Broadly speaking, here's how it goes: 0) Early pre-parse steps that don't really matter to most programs, like checking character set. We'll ignore these. 1) Tokenize the text of the program into a sequence of potentially-meaningful units. 2) Parse those tokens into some sort of meaningful "sentence". 3) Compile the syntax tree into actual code. 4) Run that code. Example: >>> code = """def f(): ... print("Hello, world", 1>=2) ... print(Ellipsis, ...) ... return True ... """ >>> In step 1, all that happens is that a stream of characters (or bytes, depending on your point of view) gets broken up into units. >>> for t in tokenize.tokenize(iter(code.encode().split(b"\n")).__next__): ... print(tokenize.tok_name[t.exact_type], t.string) It's pretty spammy, but you can see how the compiler sees the text. Note that, at this stage, there's no real difference between the NAME "def" and the NAME "print" - there are no language keywords yet. Basically, all you're doing is figuring out punctuation and stuff. Step 2 is what we'd normally consider "parsing". (It may well happen concurrently and interleaved with tokenizing, and I'm giving a simplified and conceptualized pipeline here, but this is broadly what Python does.) This compares the stream of tokens to the grammar of a Python program and attempts to figure out what it means. At this point, the linear stream turns into a recursive syntax tree, but it's still very abstract. >>> import ast >>> ast.dump(ast.parse(code)) "Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='Hello, world'), Compare(left=Constant(value=1), ops=[GtE()], comparators=[Constant(value=2)])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Name(id='Ellipsis', ctx=Load()), Constant(value=Ellipsis)], keywords=[])), Return(value=Constant(value=True))], decorator_list=[])], type_ignores=[])" (Side point: I would rather like to be able to pprint.pprint(ast.parse(code)) but that isn't a thing, at least not currently.) This is where the vast majority of SyntaxErrors come from. Your code is a sequence of tokens, but those tokens don't mean anything. It doesn't make sense to say "print(def f[return)]" even though that'd tokenize just fine. The trouble with the notion of "keeping going after finding an error" is that, when you find an error, there are almost always multiple possible ways that this COULD have been interpreted differently. It's as likely to give nonsense results as actually useful ones. (Note that, in contrast to the tokenization stage, this version distinguishes between the different types of word. The "def" has resulted in a FunctionDef node, the "print" is a Name lookup, and both "..." and "True" have now become Constant nodes - previously, "..." was a special Ellipsis token, but "True" was just a NAME.) Step 3: the abstract syntax tree gets parsed into actual runnable code. This is where that small handful of other SyntaxErrors come from. With these errors, you absolutely _could_ carry on and report multiple; but it's not very likely that there'll actually *be* more than one of them in a file. Here's some perfectly valid AST parsing: >>> ast.dump(ast.parse("from __future__ import the_past")) "Module(body=[ImportFrom(module='__future__', names=[alias(name='the_past')], level=0)], type_ignores=[])" >>> ast.dump(ast.parse("from __future__ import braces")) "Module(body=[ImportFrom(module='__future__', names=[alias(name='braces')], level=0)], type_ignores=[])" >>> ast.dump(ast.parse("def f():\n\tdef g():\n\t\tnonlocal x\n")) "Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[FunctionDef(name='g', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Nonlocal(names=['x'])], decorator_list=[])], decorator_list=[])], type_ignores=[])" If you were to try to actually compile those to bytecode, they would fail: >>> compile(ast.parse("from __future__ import braces"), "-", "exec") Traceback (most recent call last): File "", line 1, in File "-", line 1 SyntaxError: not a chance And finally, step 4 is actually running the compiled bytecode. Any errors that happen at THIS stage are going to be run-time errors, not syntax errors (a SyntaxError raised at run time would be from compiling other code). > So is the OP asking for something other than a Python Interpreter that > normally halts after some kind of error? Tools like a linter may indeed fit > that mold. Yes, but linters are still going to go through the same process laid out above. So if you have a huge pile of code that misuses "await" in non-async functions, sure! Maybe a linter could half-compile the code, then probe it repeatedly until it gets past everything. That's not exactly a common case, though. More likely, you'll have parsing errors, and the only way to "move past" a parsing error is to guess at what token should be added or removed to make it "kinda work". Alternatively, you'll get some kind of messy heuristics to try to restart parsing part way down, but that's pretty imperfect too. > This may limit some of the objections of when an error makes it hard for the > parser to find some recovery point to continue from as no code is being run > and no harmful side effects happen by continuing just an analysis. It's pretty straight-forward to ensure that no code is run - just compile it without running it. It's still possible to attack the compiler itself, but far less concerning than running arbitrary code. Attacks on the compiler are usually deliberate; code you don't want to run yet might be a perfectly reasonable call to os.unlink()... > Time to go read some books about modern ways to evaluate a language based on > more mathematical rules including more precisely what is syntax versus ... > > Suggestions? > I'd recommend looking at Python's compile() function, the ast and tokenizer modules, and everything that they point to. ChrisA From avi.e.gross at gmail.com Tue Oct 11 02:42:16 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Tue, 11 Oct 2022 02:42:16 -0400 Subject: What to use for finding as many syntax errors as possible. References: <00ab01d8dd1f$2af0f9f0$80d2edd0$@gmail.com> Message-ID: <011c01d8dd3c$9ab4b520$d01e1f60$@gmail.com> I think we are in agreement here, Chris. My point is that the error detection and correction is now done at levels where there is not much need to use earlier and inefficient methods like parity bits set aside. We use protocols like TCP and IP and layers above them and above those to maintain the integrity of packets and sessions and forms of encryption allowing things like authentication. There is tons of overhead, even when some is fairly efficient, but we hardly notice it unless things go wrong. So written language sent (as in this email/post) does not need lots of redundancy and all the extra effort is, IMNSHO opinion, largely wasted. If I see a bear, I do not wish to check their genitals or DNA to determine their irrelevant gender before asking someone to run from it. If I happen to know the gender, as in a zoo, gender only matters for things like breeding purposes. I do not want to memorize terms in languages that have not only words like lion and lioness or duck and drake and goose and gander, but for EVERYTHING in some sense so I can say the equivalent of ANIMAL-male and ANIMAL-female with unique words. Life would be so much simpler if I could say your dog was nice and not be corrected that it was a bitch and I used the wrong word endings. If I really wanted to say it was a female dog, well I could just add a qualified. Most of the time, who cares? The same applies to so much grammatical nonsense which is also usually riddled with endless exceptions to the many rules. Make the languages simple with little redundancy and thus far easier to learn. I can say similar things about some programming languages that either have way too many rules or too few of the right ones. There are tradeoffs and if you want a powerful language it will likely not be easy to control. If you want a very regulated language, you may find it not very useful as many things are hard to do ad others not possible. I know that strongly typed languages often have to allow some method of cheating such as unions of data types, or using a parent class as the sort of object-type to allow disparate objects to live together. Python is far from the most complex but as noted, it is not trivial to evaluate even the syntax past errors. But I admit it is fun and a challenge to learn both kinds and I spent much of my time doing so. I like the flexibility of seeing different approaches and holding contradictions in my mind while accepting both and yet neither! LOL! -----Original Message----- From: Python-list On Behalf Of Chris Angelico Sent: Monday, October 10, 2022 11:24 PM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On Tue, 11 Oct 2022 at 14:13, wrote: > With the internet today, we are used to expecting error correction to > come for free. Do you really need one of every 8 bits to be a parity > bit, which only catches may half of the errors... Fortunately, we have WAY better schemes than simple parity, which was only really a thing in the modem days. (Though I would say that there's still a pretty clear distinction between a good message where everything has correct parity, and line noise where half of them don't.) Hamming codes can correct one-bit errors (and detect two-bit errors) at a price of log2(size)+1 bits of space. Here's a great rundown: https://www.youtube.com/watch?v=X8jsijhllIA There are other schemes too, but Hamming codes are beautifully elegant and easy to understand. ChrisA -- https://mail.python.org/mailman/listinfo/python-list From avi.e.gross at gmail.com Tue Oct 11 03:10:51 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Tue, 11 Oct 2022 03:10:51 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> Message-ID: <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> Thanks for a rather detailed explanation of some of what we have been discussing, Chris. The overall outline is about what I assumed was there but some of the details were, to put it politely, fuzzy. I see resemblances to something like how a web page is loaded and operated. I mean very different but at some level not so much. I mean a typical web page is read in as HTML with various keyword regions expected such as ... or
...
with things often cleanly nested in others. The browser makes nodes galore in some kind of tree format with an assortment of objects whose attributes or methods represent aspects of what it sees. The resulting treelike structure has names like DOM. To a certain approximation, this tree starts a certain way but is regularly being manipulated (or perhaps a copy is) as it regularly is looked at to see how to display it on the screen at the moment based on the current tree contents and another set of rules in Cascading Style Sheets. But bits and pieces of JavaScript are also embedded or imported that can read aspects of the tree (and more) and modify the contents and arrange for all kinds of asynchronous events when bits of code are invoked such as when you click a button or hover or when an image finishes loading or every 100 milliseconds. It can insert new objects into the DOM too. And of course there can be interactions with restricted local storage as well as with servers and code running there. It is quite a mess but in some ways I see analogies. Your program reads a stream of data and looks for tokens and eventually turns things into a tree of sorts that represents relationships to a point. Additional structures eventually happen at run time that let you store collections of references to variables such as environments or namespaces and the program derived from the trees makes changes as it goes and in a language like Python can even possibly change the running program in some ways. These are not at all the same thing but share a certain set of ideas and methods and can be very powerful as things interact. In the web case, the CSS may search for regions with some class or ID or that are the third element of a bullet list and more, using powerful tools like jQuery, and make changes. A CSS rule that previously ignored some region as not having a particular class, might start including it after a JavaScript segment is aroused while waiting on an event listener for say a mouse hovering over an area and then changes that part of the DOM (like a node) to be in that class. Suddenly the area on your screen changes background or whatever the CSS now dictates. We have multiple systems written in an assortment of "languages" that complement each other. Some running programs, especially ones that use asynchronous methods like threads or callbacks on events, such as a GUI, can effectively do similar things. In effect the errors in the web situation have such analogies too as in what happens if a region of HTML is not well-formed or uses a keyword not recognized. This becomes even more interesting in XML where anything can be a keyword and you often need other kinds of files (often also in ML) to define what the XML can be like and what restrictions it may have such as can a have multiple authors but only one optional publication date and so on. It can be fascinating and highly technical. So I am up for a challenge of studying anything from early compilers for languages of my youth to more recent ways including some like what you show. I have time to kill and this might be more fun than other things, for a while. There was a guy around a few years ago who suggested he would create a system where you could create a series of some kind of configuration files for ANY language and his system would them compile or run programs for each and every such language? Was that on this forum? What ever happened to him? But although what he promised seemed a bit too much, I can see from your comments below how in some ways a limited amount of that might be done for some subset of languages which can be parsed and manipulated as described. -----Original Message----- From: Python-list On Behalf Of Chris Angelico Sent: Monday, October 10, 2022 11:55 PM To: python-list at python.org Subject: Re: What to use for finding as many syntax errors as possible. On Tue, 11 Oct 2022 at 14:26, wrote: > > I stand corrected Chris, and others, as I pay the sin tax. > > Yes, there are many kinds of errors that logically fall into different > categories or phases of evaluation of a program and some can be > determined by a more static analysis almost on a line by line (or > "statement" or "expression", ...) basis and others need to sort of > simulate some things and look back and forth to detect possible > incompatibilities and yet others can only be detected at run time and > likely way more categories depending on the language. > > But when I run the Python interpreter on code, aren't many such phases > done interleaved and at once as various segments of code are parsed > and examined and perhaps compiled into block code and eventually executed? Hmm, depends what you mean. Broadly speaking, here's how it goes: 0) Early pre-parse steps that don't really matter to most programs, like checking character set. We'll ignore these. 1) Tokenize the text of the program into a sequence of potentially-meaningful units. 2) Parse those tokens into some sort of meaningful "sentence". 3) Compile the syntax tree into actual code. 4) Run that code. Example: >>> code = """def f(): ... print("Hello, world", 1>=2) ... print(Ellipsis, ...) ... return True ... """ >>> In step 1, all that happens is that a stream of characters (or bytes, depending on your point of view) gets broken up into units. >>> for t in tokenize.tokenize(iter(code.encode().split(b"\n")).__next__): ... print(tokenize.tok_name[t.exact_type], t.string) It's pretty spammy, but you can see how the compiler sees the text. Note that, at this stage, there's no real difference between the NAME "def" and the NAME "print" - there are no language keywords yet. Basically, all you're doing is figuring out punctuation and stuff. Step 2 is what we'd normally consider "parsing". (It may well happen concurrently and interleaved with tokenizing, and I'm giving a simplified and conceptualized pipeline here, but this is broadly what Python does.) This compares the stream of tokens to the grammar of a Python program and attempts to figure out what it means. At this point, the linear stream turns into a recursive syntax tree, but it's still very abstract. >>> import ast >>> ast.dump(ast.parse(code)) "Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Constant(value='Hello, world'), Compare(left=Constant(value=1), ops=[GtE()], comparators=[Constant(value=2)])], keywords=[])), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Name(id='Ellipsis', ctx=Load()), Constant(value=Ellipsis)], keywords=[])), Return(value=Constant(value=True))], decorator_list=[])], type_ignores=[])" (Side point: I would rather like to be able to pprint.pprint(ast.parse(code)) but that isn't a thing, at least not currently.) This is where the vast majority of SyntaxErrors come from. Your code is a sequence of tokens, but those tokens don't mean anything. It doesn't make sense to say "print(def f[return)]" even though that'd tokenize just fine. The trouble with the notion of "keeping going after finding an error" is that, when you find an error, there are almost always multiple possible ways that this COULD have been interpreted differently. It's as likely to give nonsense results as actually useful ones. (Note that, in contrast to the tokenization stage, this version distinguishes between the different types of word. The "def" has resulted in a FunctionDef node, the "print" is a Name lookup, and both "..." and "True" have now become Constant nodes - previously, "..." was a special Ellipsis token, but "True" was just a NAME.) Step 3: the abstract syntax tree gets parsed into actual runnable code. This is where that small handful of other SyntaxErrors come from. With these errors, you absolutely _could_ carry on and report multiple; but it's not very likely that there'll actually *be* more than one of them in a file. Here's some perfectly valid AST parsing: >>> ast.dump(ast.parse("from __future__ import the_past")) "Module(body=[ImportFrom(module='__future__', names=[alias(name='the_past')], level=0)], type_ignores=[])" >>> ast.dump(ast.parse("from __future__ import braces")) "Module(body=[ImportFrom(module='__future__', names=[alias(name='braces')], level=0)], type_ignores=[])" >>> ast.dump(ast.parse("def f():\n\tdef g():\n\t\tnonlocal x\n")) "Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[FunctionDef(name='g', args=arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[]), body=[Nonlocal(names=['x'])], decorator_list=[])], decorator_list=[])], type_ignores=[])" If you were to try to actually compile those to bytecode, they would fail: >>> compile(ast.parse("from __future__ import braces"), "-", "exec") Traceback (most recent call last): File "", line 1, in File "-", line 1 SyntaxError: not a chance And finally, step 4 is actually running the compiled bytecode. Any errors that happen at THIS stage are going to be run-time errors, not syntax errors (a SyntaxError raised at run time would be from compiling other code). > So is the OP asking for something other than a Python Interpreter that > normally halts after some kind of error? Tools like a linter may > indeed fit that mold. Yes, but linters are still going to go through the same process laid out above. So if you have a huge pile of code that misuses "await" in non-async functions, sure! Maybe a linter could half-compile the code, then probe it repeatedly until it gets past everything. That's not exactly a common case, though. More likely, you'll have parsing errors, and the only way to "move past" a parsing error is to guess at what token should be added or removed to make it "kinda work". Alternatively, you'll get some kind of messy heuristics to try to restart parsing part way down, but that's pretty imperfect too. > This may limit some of the objections of when an error makes it hard > for the parser to find some recovery point to continue from as no code > is being run and no harmful side effects happen by continuing just an analysis. It's pretty straight-forward to ensure that no code is run - just compile it without running it. It's still possible to attack the compiler itself, but far less concerning than running arbitrary code. Attacks on the compiler are usually deliberate; code you don't want to run yet might be a perfectly reasonable call to os.unlink()... > Time to go read some books about modern ways to evaluate a language > based on more mathematical rules including more precisely what is syntax versus ... > > Suggestions? > I'd recommend looking at Python's compile() function, the ast and tokenizer modules, and everything that they point to. ChrisA -- https://mail.python.org/mailman/listinfo/python-list From roel at roelschroeven.net Tue Oct 11 04:00:21 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Tue, 11 Oct 2022 10:00:21 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <74afbf76-e75c-7d59-e6b6-93af63ebba0a@roelschroeven.net> Op 10/10/2022 om 19:08 schreef Robert Latest via Python-list: > Antoon Pardon wrote: > > I would like a tool that tries to find as many syntax errors as possible > > in a python file. > > I'm puzzled as to when such a tool would be needed. How many syntax errors can > you realistically put into a single Python file before compiling it for the > first time? I've been following the discussion from a distance and the whole time I've been wondering the same thing. Especially when you have unit tests, as Antoon said he has, I can't really imagine a situation where you add so much code in one go without running it that you introduce a painful amount of syntax errors. My solution would be to use a modern IDE with a linter, possibly with style warnings disabled, which will flag syntax errors as soon as you type them. Possibly combined with a TDD-style tactic which also prevents large amounts of errors (any errors) to build up. But I have the impression that any of those doesn't fit in Antoon's workflow. -- "Peace cannot be kept by force. It can only be achieved through understanding." -- Albert Einstein From antoon.pardon at vub.be Tue Oct 11 05:53:17 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Tue, 11 Oct 2022 11:53:17 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <7c861f12-2a12-d711-fccb-71211279c80d@vub.be> Op 10/10/2022 om 19:08 schreef Robert Latest via Python-list: > Antoon Pardon wrote: >> I would like a tool that tries to find as many syntax errors as possible >> in a python file. > I'm puzzled as to when such a tool would be needed. How many syntax errors can > you realistically put into a single Python file before compiling it for the > first time? Why are you puzzled? I don't need to make that many syntaxt errors to find such a tool useful. -- Antoon Pardon From gweatherby at uchc.edu Tue Oct 11 07:26:15 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Tue, 11 Oct 2022 11:26:15 +0000 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <008201d8dd16$718fd420$54af7c60$@gmail.com> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> Message-ID: Sure it does. They?re optional and not enforced at runtime, but I find them useful when writing code in PyCharm: import os from os import DirEntry de : DirEntry for de in os.scandir('/tmp'): print(de.name) de = 7 print(de) Predeclaring de allows me to do the tab completion thing with DirEntry fields / methods From: Python-list on behalf of avi.e.gross at gmail.com Date: Monday, October 10, 2022 at 10:11 PM To: python-list at python.org Subject: RE: What to use for finding as many syntax errors as possible. *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** Michael, A reasonable question. Python lets you initialize variables but has no explicit declarations. From rosuav at gmail.com Tue Oct 11 07:39:07 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 11 Oct 2022 22:39:07 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> Message-ID: On Tue, 11 Oct 2022 at 18:12, wrote: > > Thanks for a rather detailed explanation of some of what we have been > discussing, Chris. The overall outline is about what I assumed was there but > some of the details were, to put it politely, fuzzy. > > I see resemblances to something like how a web page is loaded and operated. > I mean very different but at some level not so much. > > I mean a typical web page is read in as HTML with various keyword regions > expected such as ... or
...
with things > often cleanly nested in others. The browser makes nodes galore in some kind > of tree format with an assortment of objects whose attributes or methods > represent aspects of what it sees. The resulting treelike structure has > names like DOM. Yes. The basic idea of "tokenize, parse, compile" can be used for pretty much any language - even English, although its grammar is a bit more convoluted than most programming languages, with many weird backward compatibility features! I'll parse your last sentence above: LETTERS The SPACE LETTERS resulting SPACE ... you get the idea LETTERS like SPACE LETTERS DOM FULLSTOP # or call this token PERIOD if you're American Now, we can group those tokens into meaningful sets. Sentence(type=Statement, subject=Noun(name="structure", addenda=[ Article(type=The), Adjective(name="treelike"), ]), verb=Verb(type=Being, name="has", addenda=[]), object=Noun(name="name", plural=True, addenda=[ Adjective(phrase=Phrase(verb=Verb(name="like"), object=Noun(name="DOM"), ]), ) Grammar nerds will probably dispute some of the awful shorthanding I did here, but I didn't want to devise thousands of AST nodes just for this :) > To a certain approximation, this tree starts a certain way but is regularly > being manipulated (or perhaps a copy is) as it regularly is looked at to see > how to display it on the screen at the moment based on the current tree > contents and another set of rules in Cascading Style Sheets. Yep; the DOM tree is initialized from the HTML (usually - it's possible to start a fresh tree with no HTML) and then can be manipulated afterwards. > These are not at all the same thing but share a certain set of ideas and > methods and can be very powerful as things interact. Oh absolutely. That's why there are languages designed to help you define other languages. > In effect the errors in the web situation have such analogies too as in what > happens if a region of HTML is not well-formed or uses a keyword not > recognized. Aaaaand they're horribly horribly messy, due to a few decades of sloppy HTML programmers and the desire to still display the page even if things are messed up :) But, again, there's a huge difference between syntactic errors (like omitting a matching angle bracket) and semantic errors (a keyword not known, like using when you should have used ). In the latter case, you can still build a DOM tree, but you have an unknown element; in the former case, you have to guess at what the author meant, just to get anything going at all. > There was a guy around a few years ago who suggested he would create a > system where you could create a series of some kind of configuration files > for ANY language and his system would them compile or run programs for each > and every such language? Was that on this forum? What ever happened to him? That was indeed on this forum, and I have no idea what happened to him. Maybe he realised that all he'd invented was the Unix shebang? ChrisA From antoon.pardon at vub.be Tue Oct 11 10:30:05 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Tue, 11 Oct 2022 16:30:05 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <005101d8dc51$6181ae20$24850a60$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> <005101d8dc51$6181ae20$24850a60$@gmail.com> Message-ID: <908de019-0d7b-b165-7673-9a0d1b334878@vub.be> Op 10/10/2022 om 04:38 schreef avi.e.gross at gmail.com: > [This is an answer for Peter and can easily be skipped by those who know or > have no wish to.] > > Strictly speaking Peter, the word "pipe" may not mean quite something in > Python but other concepts like chaining may be better. > > The original use of the word I am used to was at the UNIX shell level where > an in-core data structure called a pipe was used to connect the output of > one process to the inputr of another, sometimes in long chains like: > > cat file1 file2 file3 | grep pattern | ... | lp Something like that can be done in python with the same kind of syntax: https://code.activestate.com/recipes/580625-collection-pipeline-in-python/ I have my own python3 module with stuff like that and I find it very usefull. -- Antoon Pardon From evagreven16 at gmail.com Tue Oct 11 03:20:46 2022 From: evagreven16 at gmail.com (evagreven16 at gmail.com) Date: Tue, 11 Oct 2022 09:20:46 +0200 Subject: WG: Modify setup window In-Reply-To: <001001d8dd41$d12b53c0$7381fb40$@gmail.com> References: <000001d8dd3e$0430af80$0c920e80$@gmail.com> <001001d8dd41$d12b53c0$7381fb40$@gmail.com> Message-ID: <001c01d8dd41$fb52a5e0$f1f7f1a0$@gmail.com> Hi, this window comes up every time I try to run the code. I am not sure how to solve it. I tried to repair and modify but it didn?t change anything. Kind regards, Eva From mats at wichmann.us Tue Oct 11 11:30:49 2022 From: mats at wichmann.us (Mats Wichmann) Date: Tue, 11 Oct 2022 09:30:49 -0600 Subject: WG: Modify setup window In-Reply-To: <001c01d8dd41$fb52a5e0$f1f7f1a0$@gmail.com> References: <000001d8dd3e$0430af80$0c920e80$@gmail.com> <001001d8dd41$d12b53c0$7381fb40$@gmail.com> <001c01d8dd41$fb52a5e0$f1f7f1a0$@gmail.com> Message-ID: <1cdeb36a-1ed8-9109-97bc-25910405a411@wichmann.us> On 10/11/22 01:20, evagreven16 at gmail.com wrote: > > > Hi, > > > > this window comes up every time I try to run the code. I am not sure how to > solve it. I tried to repair and modify but it didn?t change anything. > We don't know what you're asking, because this list doesn't forward images. You'll need to explain the problem in words - or select text and paste it if possible. From the subject line, there's a reasonable chance you're rerunning the installer, since that seems to come up a lot. That won't get you Python itself - it's just doing its job, which is to *manage* the Python installation. You can delete the installer once you're done with it, that way there's less chance of confusion. If you're on Windows, try using the start menu to find Python. You can pick "Python 3.10 (64-bit)" to get the interpreter, or "IDLE (Python 3.10 64-bit)" to get a basic IDE (substitute appropriate version). From abdulhaseeb.azizi786 at gmail.com Tue Oct 11 11:53:37 2022 From: abdulhaseeb.azizi786 at gmail.com (Abdul Haseeb Azizi) Date: Tue, 11 Oct 2022 08:53:37 -0700 (PDT) Subject: Cannot import gdal in jupyter notebook Message-ID: Hi everyone, I am new to python and I am trying to utilize this code "from osgeo import gdal". I installed python 3.10 and also I installed anaconda3 to solve this matter but I could not succeed. When I run that code I get the following error. --------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) Cell In [1], line 1 ----> 1 from osgeo import gdal ModuleNotFoundError: No module named 'osgeo' I also tried to create anaconda environment and enter the following codes: conda crate --name pygdal conda activate pygdal conda install -c conda-forge gdal I don't what is the problem. Any help is appreciated to solve this matter. Looking forward to hear from you. with regards Abdul From avi.e.gross at gmail.com Tue Oct 11 13:58:24 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Tue, 11 Oct 2022 13:58:24 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <908de019-0d7b-b165-7673-9a0d1b334878@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> <005101d8dc51$6181ae20$24850a60$@gmail.com> <908de019-0d7b-b165-7673-9a0d1b334878@vub.be> Message-ID: <002d01d8dd9b$0f11e510$2d35af30$@gmail.com> Anton, Your example overlaps with the use of generators in Python to do variants of the same pipeline ideas. But is that native python or some extension where "|" has been modified to mean something other than a form of OR in some places? What module do you need to load to make that happen? I think there is a long history in Computing where it may be easier to write languages that do things in what some call Reverse Polish Notation and you have languages of the LISP variety, as one example, that suggest code like (MULT (ADD 1 2) (SUB 5 3)) which gets really annoying for longer calculations like say the quadratic formula. People (and many programmers are still people) often prefer some form of infix notation even if the machine gets re-arranged code that does something like the above. Pipes in UNIX had real asynchronous but coordinated meaning and often ran quite a bit faster as some parts could run while others were doing I/O or otherwise waiting. BUT it often led to fairly quick and sloppy solutions that probably could have been done faster within one application without lots of overhead. The kind of pipelines we have been talking about, mainly in Python albeit I mentioned the versions in R, are largely syntactic sugar where often there is really a single thread of execution which can range from almost meaningless (as in each part runs to completion and generates lots of data that is then used by the next stage and eventually intermediates are garbage collected) to some with a sort of zig-zag approach where smaller chunks of data are made as various functions are called and yield a partial result and go to sleep as the next function that called it does something similar. There may be little or no speedup of the code or even a slowing down. What would be needed for a better emulation of the UNIX (and later LINUX and etc.) pipeline is closer to having asynchronous processes running on multiple cores and yet communicating efficiently. And it need not be linear. Consider a merge sort as an example where each level subdivides the data and calls multiple others to recursively work on it and the parent waits for them all to complete and then merges the results. Some algorithms along those lines can be run across machines entirely or using machines all over the internet. You can imagine a chess program that ships all reasonable possible next moves to others and gets back some analysis of how well each move is rated based on multiple levels of look-ahead from each child that farmed out the possible moves to the next level. This kind of approach can be treelike or a generalized graph and also in higher dimensions. An example of what I mean by dimensions is tools that work on XML or just HTML, like xpath or jquery and have various "dimensions" such as following in a direction that chooses based on ID versus a direction based on CLASS versus a direction based on ancestry, or siblings, or ordinality and many other such attributes. But enough of that. Back to your point, the map/filter/reduce kinds of functionality have long been used in various kinds of functional programming in many languages and are a way to do pipelining, albeit usually in a more RPN way by nesting function calls within function calls in a harder-to-read way. If the syntax change allows a pipe symbol so it can be written infix, that helps programmers who prefer to think more linearly. But since the original topic here was loosely about loops and the silly choice (there was no great choice) of re-using the ELSE keyword, I note how commonly we often use loops as in: for first in iterator: for second in iterator: ... The second (and deeper) loop(s) sort of run faster than the outer ones. But compare that to how you might write a comprehension like: [x*y*z for x in range(5) for y in range(5) for z in range(5)] The above acts sort of like a pipeline as in the first "for" sends 0 to 4 to the second which passes that along plus another 0..4 to the next one which passes that plus it's own contribution to the main body which multiplies them and adds them to a growing list. Of course the problem in the example is that the main body is in front even as it is I a sense done last, and the entire construct does the collecting of the results invisibly into a list. For some people I know, the nested loop version makes more sense and for some people the comprehension method seems more inline, or at least condensed. My point is perhaps both subtle and blatant. There are tons of IDEAS out there that superficially have some ways they can be perceived as similar but ultimately can be seen to differ in many ways and are not the same thing and often are not interchangeable. A pipeline construct with some kinds of generators can generate an "infinite" amount of data in theory, but in practice only an indefinite amount, such as the first N primes with N not being a constant. Another pipeline that calculates the first million primes and feeds them in a pipeline that perhaps quits after seeing the first few dozen, may look similar but wastes lots of resources in computing too much and storing too much. And it fails if the program turns out to need more than a million. The map and filter and reduce methods often call a function repeatedly on data and combine the results. But if you use a generator, calling it repeatedly is more like continuing the existing instance that is just hibernating and can have very different results. Similarly, languages that are vectorized may do better to not be called through these functions as they can perform the many operations on their own on known data of a known length. But they can often be easy to pipeline in various ways with other such vectorized functions somewhat more directly. This forum often talks about what methods seem more "pythonic" than others. Arguably generators are now part of a pythonic way for many. Not sure if various ideas of "pipelines" are equally pythonic and some may really be rather foreign to many programmers, at least until they catch on. Avi -----Original Message----- From: Python-list On Behalf Of Antoon Pardon Sent: Tuesday, October 11, 2022 10:30 AM To: python-list at python.org Subject: Re: for -- else: what was the motivation? Op 10/10/2022 om 04:38 schreef avi.e.gross at gmail.com: > [This is an answer for Peter and can easily be skipped by those who > know or have no wish to.] > > Strictly speaking Peter, the word "pipe" may not mean quite something > in Python but other concepts like chaining may be better. > > The original use of the word I am used to was at the UNIX shell level > where an in-core data structure called a pipe was used to connect the > output of one process to the inputr of another, sometimes in long chains like: > > cat file1 file2 file3 | grep pattern | ... | lp Something like that can be done in python with the same kind of syntax: https://code.activestate.com/recipes/580625-collection-pipeline-in-python/ I have my own python3 module with stuff like that and I find it very usefull. -- Antoon Pardon -- https://mail.python.org/mailman/listinfo/python-list From evagreven16 at gmail.com Tue Oct 11 14:03:00 2022 From: evagreven16 at gmail.com (evagreven16 at gmail.com) Date: Tue, 11 Oct 2022 20:03:00 +0200 Subject: Please remove me from the python list Message-ID: <001901d8dd9b$b3e9c120$1bbd4360$@gmail.com> From list1 at tompassin.net Tue Oct 11 14:11:56 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 11 Oct 2022 14:11:56 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> Message-ID: <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> On 10/11/2022 3:10 AM, avi.e.gross at gmail.com wrote: > I see resemblances to something like how a web page is loaded and operated. > I mean very different but at some level not so much. > > I mean a typical web page is read in as HTML with various keyword regions > expected such as ... or
...
with things > often cleanly nested in others. The browser makes nodes galore in some kind > of tree format with an assortment of objects whose attributes or methods > represent aspects of what it sees. The resulting treelike structure has > names like DOM. To bring things back to the context of the original post, actual web browsers are extremely tolerant of HTML syntax errors (including incorrect nesting of tags) in the documents they receive. They usually recover silently from errors and are able to display the rest of the page. Usually they manage this correctly. The OP would like to have a parser or checker that could do the same, plus giving an output showing where each of the errors happened. I can imagine such a parser also reporting which lines it had to skip before it was able to recover. From PythonList at DancesWithMice.info Tue Oct 11 15:35:46 2022 From: PythonList at DancesWithMice.info (dn) Date: Wed, 12 Oct 2022 08:35:46 +1300 Subject: [Meeting] Problem-solving, perspectives, programming, and presentation, 19Oct Message-ID: <5d23c9e1-d600-f0b3-ab4e-10728245ac3b@DancesWithMice.info> With all that "p"-alliteration, it must be a Pppresentation with the virtual-Auckland branch of NZPUG! Wed 19 Oct, 1800 for 1830 ~ 2030 NZDT 0500, 0530, and 0730 UTC+13 resp by web-conference Nathan Smith had an 'itch' caused by a problem related to the game of Scrabble. Solving a problem with Python, from start-to-finish. A journey of challenges, a lesson of not giving in and hopefully a good story all round. Featuring, steps forwards, brick-walls, data-structures related to words, dictionaries (of both definitions) and Directed Acyclic Word Graphs (DAWG - application of DAG graph/network structures). Plus, a blind person's perspective on coding through the project, presenting overview information on the way a blind person may access code and what similarities or differences may crop up. Creative Coding With Python: Learn how to code simple visuals in Python for games, innovative stats, simulations and generative art using a flavour of the processing library. This can be incredibly useful for teaching programming, visualising concepts and sharpening thinking skills. This list's own Abdur-Rahman Janhangeer organises the Python Mauritius User Group and FlaskCon* (amongst many other contributions to the Python Community including graphic presentation libraries) * Flask is a very popular web framework More info about the group, and to RSVP (and thus receive the meeting URL) see Meetup group at: https://www.meetup.com/nzpug-auckland/events/njdjssydcnbzb/ Regards =dn (Pete and DJ) From list1 at tompassin.net Tue Oct 11 15:38:54 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 11 Oct 2022 15:38:54 -0400 Subject: Cannot import gdal in jupyter notebook In-Reply-To: References: Message-ID: On Windows, when I tried to install gdal using pip, it needed to compile part of it. I'm not set up with the Microsoft compiler and header files, so that failed. If you are on Windows, you will need to look for a binary wheel to install, or install and configure the compiler and header files. On 10/11/2022 11:53 AM, Abdul Haseeb Azizi wrote: > Hi everyone, > I am new to python and I am trying to utilize this code "from osgeo import gdal". I installed python 3.10 and also I installed anaconda3 to solve this matter but I could not succeed. When I run that code I get the following error. > --------------------------------------------------------------------------- > ModuleNotFoundError Traceback (most recent call last) > Cell In [1], line 1 > ----> 1 from osgeo import gdal > > ModuleNotFoundError: No module named 'osgeo' > > I also tried to create anaconda environment and enter the following codes: > conda crate --name pygdal > conda activate pygdal > conda install -c conda-forge gdal > > I don't what is the problem. Any help is appreciated to solve this matter. > Looking forward to hear from you. > > with regards > Abdul From giladsmum at gmail.com Tue Oct 11 15:32:23 2022 From: giladsmum at gmail.com (SquidBits _) Date: Tue, 11 Oct 2022 12:32:23 -0700 (PDT) Subject: flattening lists Message-ID: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. I have had to flatten lists quite a few times and it's quite tedious to type out. It feels like this should be something built in to python, anyone else think this way? From lukasz at langa.pl Tue Oct 11 15:58:32 2022 From: lukasz at langa.pl (=?utf-8?Q?=C5=81ukasz_Langa?=) Date: Tue, 11 Oct 2022 21:58:32 +0200 Subject: [RELEASE] Python versions 3.10.8, 3.9.15, 3.8.15, 3.7.15 now available Message-ID: <75633583-24AC-4749-9BFF-DE67ECFDE1E4@langa.pl> D?j? vu? Right, a month after the expedited releases we are doing the dance again. This coincides with the regular scheduled time for 3.10.8 but since we accrued a few fixes in 3.7 - 3.9 as well, we?re again releasing all four editions at the same time. We?re not promising to continue at this pace ? Security content this time CVE-2022-40674: bundled libexpat was upgraded from 2.4.7 to 2.4.9 which fixes a heap use-after-free vulnerability in function doContent gh-97616: a fix for a possible buffer overflow in list *= int gh-97612: a fix for possible shell injection in the example script get-remote-certificate.py (this issue originally had a CVE assigned to it, which its author withdrew) gh-96577: a fix for a potential buffer overrun in msilib Python 3.10.8 Get it here: https://www.python.org/downloads/release/python-3108/ As a bugfix release coming a mere month after an out-of-schedule security release, 3.10.8 is somewhat smaller compared to 3.9.8 released at the same stage of the release cycle a year ago. There?s 151 commits vs 204 in 3.9. It?s still a larger release than 3.10.7 at 113 commits. One way or the other, it?s worth checking out the change log . And now for something completely different Granular convection is a phenomenon where granular material subjected to shaking or vibration will exhibit circulation patterns similar to types of fluid convection. It is sometimes described as the Brazil nut effect when the largest particles end up on the surface of a granular material containing a mixture of variously sized objects; this derives from the example of a typical container of mixed nuts, where the largest will be Brazil nuts. The phenomenon is also known as the muesli effect since it is seen in packets of breakfast cereal containing particles of different sizes but similar densities, such as muesli mix. Under experimental conditions, granular convection of variously sized particles has been observed forming convection cells similar to fluid motion. We hope you enjoy the new releases! Thanks to all of the many volunteers who help make Python Development and these releases possible! Please consider supporting our efforts by volunteering yourself or through organization contributions to the Python Software Foundation. Your friendly release team, Ned Deily @nad Steve Dower @steve.dower Pablo Galindo Salgado @pablogsal ?ukasz Langa @ambv -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From larry.martell at gmail.com Tue Oct 11 15:58:53 2022 From: larry.martell at gmail.com (Larry Martell) Date: Tue, 11 Oct 2022 12:58:53 -0700 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: On Tue, Oct 11, 2022 at 12:48 PM SquidBits _ wrote: > > Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. > > [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > > I have had to flatten lists quite a few times and it's quite tedious to type out. It feels like this should be something built in to python, anyone else think this way? x = [[1,2,3],[4,5,6,7],[8,9]] [i for j in x for i in j] [1, 2, 3, 4, 5, 6, 7, 8, 9] From rosuav at gmail.com Tue Oct 11 16:00:50 2022 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 12 Oct 2022 07:00:50 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> Message-ID: On Wed, 12 Oct 2022 at 05:23, Thomas Passin wrote: > > On 10/11/2022 3:10 AM, avi.e.gross at gmail.com wrote: > > I see resemblances to something like how a web page is loaded and operated. > > I mean very different but at some level not so much. > > > > I mean a typical web page is read in as HTML with various keyword regions > > expected such as ... or
...
with things > > often cleanly nested in others. The browser makes nodes galore in some kind > > of tree format with an assortment of objects whose attributes or methods > > represent aspects of what it sees. The resulting treelike structure has > > names like DOM. > > To bring things back to the context of the original post, actual web > browsers are extremely tolerant of HTML syntax errors (including > incorrect nesting of tags) in the documents they receive. They usually > recover silently from errors and are able to display the rest of the > page. Usually they manage this correctly. Having had to debug tiny errors in HTML pages that resulted in extremely weird behaviour, I'm not sure that I agree that they usually manage correctly. Fundamentally, they guess, and guesswork is never reliable. ChrisA From david at lowryduda.com Tue Oct 11 16:02:55 2022 From: david at lowryduda.com (David Lowry-Duda) Date: Tue, 11 Oct 2022 16:02:55 -0400 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: On Tue, Oct 11, 2022 at 12:32:23PM -0700, SquidBits _ wrote: >Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. > >[[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > >I have had to flatten lists quite a few times and it's quite tedious to >type out. It feels like this should be something built in to python, >anyone else think this way? I typically don't mind things that are one liners, especially if the one liner is a list comprehension. def flatten1(inlist): return [l for sublist in inlist for l in sublist] givenlist = [[1, 2, 3], [4, 5, 6, 7], [8, 9]] print(flatten1(givenlist)) def flatten2(inlist): return sum(inlist, []) print(flatten2(givenlist)) Looking up "flatten" in python's source reveals the (not at all obvious to me as I don't use chain) alternative import itertools def flatten3(inlist): return list(itertools.chain.from_iterable) print(flatten3(givenlist)) I notice that "flatten" appears many times in python's source. I didn't check how many times it's used with the same meaning, though. - DLD From PythonList at DancesWithMice.info Tue Oct 11 16:20:37 2022 From: PythonList at DancesWithMice.info (dn) Date: Wed, 12 Oct 2022 09:20:37 +1300 Subject: for -- else: what was the motivation? In-Reply-To: <00a301d8dc57$0ae19110$20a4b330$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <00a301d8dc57$0ae19110$20a4b330$@gmail.com> Message-ID: On 10/10/2022 16.19, avi.e.gross at gmail.com wrote: > I won't reply to everything Dave says and especially not the parts I fully agree with. > > I think in many situations in life there is no ONE way to do things so most advice is heuristic at best and many exceptions may exist depending on your chosen approach. As such, I do not really think in PYTHON when writing code but an amalgam of many languages with all kinds of ways of doing things and then zoom in on how to do it in the current language be it Python or R or JavaScript and so on. Yes, I am in some sense focused but also open, just as in Human languages I may mostly be thinking in English but also sometimes see words and phrases pop into my mind from other languages that mean about the same thing and then filter it out to focus on whichever language I am supposed to be using at the time. Given that we can both remember programming last-century, this surprised. (or may have misunderstood!) If we think, in German, of some parting words for an older friend departing on a long trip, and translate word-for-word into English we might come out with: "May God pickle you". There is a second step, which is to examine the 'solution' in terms of its expression (how the communication will be received), and thus the more-correct English expression would be: "May God preserve you"! The two p-words are sufficiently-similar in meaning to appear synonymous, when examined in-isolation. However, that first expression would at least bemuse an (only) English-speaker, and quite possibly confuse! One of the problems which 'appeared' when programmers were first given direct-access to the computer, eg time-sharing mini-computers; and which persists to this day, is "the rush to code". Indeed there are (still) some 'managers' who think that unless a programmer is writing code (s)he isn't 'working' - but we're only interested in our own behavior. Accordingly, "design" and "development". Back-when, some lecturers insisted that we first create a flow-chart or a pseudo-code solution for an assignment - BEFORE we coded in COBOL, FORTRAN, or whatever. In many ways, because we were learning the programming-language, most felt it very difficult to draw a flow-chart that didn't merely look like FORTRAN. (to make that worse (for ourselves) I suspect many of us performed the latter first, and then ...) Many of us will have felt this some sort of academic-exercise or even 'a nuisance', but there was 'method in their madness'! Relating back to the comment (above): when *designing* a solution/flow-charting/pseudo-code, an "amalgam" of programming constructs and human-language expressions will indeed add richness, opportunity, and alternatives. All serving to amplify analytic and design skill. Conversely, when *coding*, the skill comes from employing the (specific, programming) language to best advantage. At which time, one's JS-knowledge is almost irrelevant, because the task is to convert a design outline or planned-solution, into Python. (idiomatic, pythonic, efficient, readable, ...) -- Regards, =dn From list1 at tompassin.net Tue Oct 11 16:27:07 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 11 Oct 2022 16:27:07 -0400 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: <76ef596d-6d00-178f-828f-a27fb6b02477@tompassin.net> Is this what you usually do? l1 = [[1,2,3],[4,5,6,7],[8,9]] l2 = [] for lz in l1: l2.extend(lz) print(l2) # [1,2,3,4,5,6,7,8,9] Not all that "tedious", perhaps... I tend to accumulate little utilities like this in a file and point to it with a .pth file. Of course, you have to remember to include it if you share your program with someone else. On 10/11/2022 3:32 PM, SquidBits _ wrote: > Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. > > [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > > I have had to flatten lists quite a few times and it's quite tedious to type out. It feels like this should be something built in to python, anyone else think this way? From python at mrabarnett.plus.com Tue Oct 11 16:26:02 2022 From: python at mrabarnett.plus.com (MRAB) Date: Tue, 11 Oct 2022 21:26:02 +0100 Subject: Cannot import gdal in jupyter notebook In-Reply-To: References: Message-ID: On 2022-10-11 20:38, Thomas Passin wrote: > On Windows, when I tried to install gdal using pip, it needed to compile > part of it. I'm not set up with the Microsoft compiler and header > files, so that failed. If you are on Windows, you will need to look for > a binary wheel to install, or install and configure the compiler and > header files. > The PyPI page at https://pypi.org/project/GDAL/ has this: """ Conda GDAL can be quite complex to build and install, particularly on Windows and MacOS. Pre built binaries are provided for the conda system: https://docs.conda.io/en/latest/ By the conda-forge project: https://conda-forge.org/ """ > On 10/11/2022 11:53 AM, Abdul Haseeb Azizi wrote: >> Hi everyone, >> I am new to python and I am trying to utilize this code "from osgeo import gdal". I installed python 3.10 and also I installed anaconda3 to solve this matter but I could not succeed. When I run that code I get the following error. >> --------------------------------------------------------------------------- >> ModuleNotFoundError Traceback (most recent call last) >> Cell In [1], line 1 >> ----> 1 from osgeo import gdal >> >> ModuleNotFoundError: No module named 'osgeo' >> >> I also tried to create anaconda environment and enter the following codes: >> conda crate --name pygdal >> conda activate pygdal >> conda install -c conda-forge gdal >> >> I don't what is the problem. Any help is appreciated to solve this matter. >> Looking forward to hear from you. >> >> with regards >> Abdul > From PythonList at DancesWithMice.info Tue Oct 11 17:08:07 2022 From: PythonList at DancesWithMice.info (dn) Date: Wed, 12 Oct 2022 10:08:07 +1300 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: <05f8fc2b-807b-ca62-cce4-6219b0e51690@DancesWithMice.info> On 12/10/2022 08.32, SquidBits _ wrote: > Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. > > [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > > I have had to flatten lists quite a few times and it's quite tedious to type out. It feels like this should be something built in to python, anyone else think this way? There is a flatten function! First though, are we ONLY talking about 'flattening' a 2D list (per example, above) or might the requirements extend to multiple-dimensions? The solutions vary accordingly! Two-dimensions: (don't think this method previously-mentioned, but very readable) >>> l = [[1,2,3],[4,5,6,7],[8,9]] >>> flattened = list() >>> for element in l: ... flattened += element ... >>> flattened [1, 2, 3, 4, 5, 6, 7, 8, 9] (NB if "l" were three-dimensional, "flattened" would become 2D) Multi-dimensional: Reach for itertools: (https://docs.python.org/3/library/itertools.html#itertools.chain) >>> import itertools as it >>> iter_flattened = it.chain( *l ) >>> list( iter_flattened ) [1, 2, 3, 4, 5, 6, 7, 8, 9] Wrt "I have had to flatten lists quite a few times and it's quite tedious to type out.", isn't this a "code-smell"? Certainly motivation to generalise and write a solution as a function. Do it once, and do it right! Hence advice elsewhere to build a list-processing utility-library. On the other hand, has it already been done for us? An exercise for the reader: is reaching for itertools 'over-kill' in 2D? - speed-comparison between loading the itertools library and then employing the speedy method, or using a (built-in) for-loop at Python-speed with no import-overhead? (results will vary significantly according to len( l ), but do they remain consistently in-favor or one method or the other?) -- Regards, =dn From list1 at tompassin.net Tue Oct 11 17:09:27 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 11 Oct 2022 17:09:27 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> Message-ID: <618720ac-e43b-5f71-93b7-8d418132a3eb@tompassin.net> On 10/11/2022 4:00 PM, Chris Angelico wrote: > On Wed, 12 Oct 2022 at 05:23, Thomas Passin wrote: >> >> On 10/11/2022 3:10 AM, avi.e.gross at gmail.com wrote: >>> I see resemblances to something like how a web page is loaded and operated. >>> I mean very different but at some level not so much. >>> >>> I mean a typical web page is read in as HTML with various keyword regions >>> expected such as ... or
...
with things >>> often cleanly nested in others. The browser makes nodes galore in some kind >>> of tree format with an assortment of objects whose attributes or methods >>> represent aspects of what it sees. The resulting treelike structure has >>> names like DOM. >> >> To bring things back to the context of the original post, actual web >> browsers are extremely tolerant of HTML syntax errors (including >> incorrect nesting of tags) in the documents they receive. They usually >> recover silently from errors and are able to display the rest of the >> page. Usually they manage this correctly. > > Having had to debug tiny errors in HTML pages that resulted in > extremely weird behaviour, I'm not sure that I agree that they usually > manage correctly. Fundamentally, they guess, and guesswork is never > reliable. Still, browsers generally do a very decent job of recovery, even though perfection isn't possible. The OP wants to get help with problems in his files even if it isn't perfect, and I think that's reasonable to wish for. The link to a post about the lezer parser in a recent message on this thread is partly about how a real, practical parser can do some error correction in mid-flight, for the purposes of a programming editor (as opposed to one that has to build a correct program). From list1 at tompassin.net Tue Oct 11 17:45:25 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 11 Oct 2022 17:45:25 -0400 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <618720ac-e43b-5f71-93b7-8d418132a3eb@tompassin.net> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> <618720ac-e43b-5f71-93b7-8d418132a3eb@tompassin.net> Message-ID: On 10/11/2022 5:09 PM, Thomas Passin wrote: > The OP wants to get help with problems in > his files even if it isn't perfect, and I think that's reasonable to > wish for.? The link to a post about the lezer parser in a recent message > on this thread is partly about how a real, practical parser can do some > error correction in mid-flight, for the purposes of a programming editor > (as opposed to one that has to build a correct program). One editor that seems to do what the OP wants is Visual Studio Code. It will mark apparent errors - not just syntax errors - not limited to one per page. Sometimes it can even suggest corrections. I personally dislike the visual clutter the markings impose, but I imagine I could get used to it. VSC uses a Microsoft system they call "PyLance" - see https://devblogs.microsoft.com/python/announcing-pylance-fast-feature-rich-language-support-for-python-in-visual-studio-code/ Of course, you don't get something complex for free, and in this case the cost is having to run a separate server to do all this analysis on the fly. However, VSC handles all of that behind the scenes so you don't have to. Personally, I'd most likely go for a decent programming editor that you can set up to run a program on your file, use that to run a checker, like pyflakes for instance, and run that from time to time. You could run it when you save a file. Even if it only showed one error at a time, it would make quick work of correcting mistakes. And it wouldn't need to trigger an entire tool chain each time. My editor of choice for setting up helper "tools" like this on Windows is Editplus (non-free but cheap and very worth it), and I have both py_compile and pyflakes set up this way in it. However, as I mentioned in an earlier post, the Leo Editor (https://github.com/leo-editor/leo-editor) does this for you automatically when you save, so it's very convenient. That's what I mostly work in. From cs at cskk.id.au Tue Oct 11 18:29:42 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Wed, 12 Oct 2022 09:29:42 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: On 11Oct2022 17:45, Thomas Passin wrote: >Personally, I'd most likely go for a decent programming editor that you >can set up to run a program on your file, use that to run a checker, >like pyflakes for instance, and run that from time to time. You could >run it when you save a file. Even if it only showed one error at a >time, it would make quick work of correcting mistakes. And it wouldn't >need to trigger an entire tool chain each time. Aye. I've got my editor (vim) configured to run an autoformatter on my code when I save (this can be turned off, and parse errors prevent any reformatting). Linters I run by hand from the adjacent shell window, via a small script which runs my preferred linters with their preferred options. My current workplace triggers the CI workflow when you push commits upstream, and you can make branch names which do not trigger the CI stuff. So there's a decent separation between saving (and testing or locally running the dev code) from the CI cycle. Cheers, Cameron Simpson From grant.b.edwards at gmail.com Tue Oct 11 18:59:25 2022 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Tue, 11 Oct 2022 15:59:25 -0700 (PDT) Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <20221009081227.m6merbym7yeybswy@hjp.at> <20221009171414.n4gdtqvk5lzepblm@hjp.at> <20221009200227.dzmu2thwcsunees3@hjp.at> <005101d8dc51$6181ae20$24850a60$@gmail.com> <908de019-0d7b-b165-7673-9a0d1b334878@vub.be> <002d01d8dd9b$0f11e510$2d35af30$@gmail.com> Message-ID: <6345f54d.050a0220.45b43.2f3e@mx.google.com> On 2022-10-11, wrote: > But is that native python or some extension where "|" has been modified to > mean something other than a form of OR in some places? The latter. > What module do you need to load to make that happen? The provided link is for a page that shows the module and explains the usage. From python at mrabarnett.plus.com Tue Oct 11 19:26:10 2022 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 12 Oct 2022 00:26:10 +0100 Subject: flattening lists In-Reply-To: References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: On 2022-10-11 21:09, Stefan Ram wrote: > ram at zedat.fu-berlin.de (Stefan Ram) writes: >>. I never understood "yield from" until just now, when I was >>thinking, "Maybe this could be the piece that fits in here!" > > PS: If I'm starting to think about it: Having succeeded > after using it by trial in one case does not mean that I > have understood it! > > This: yield from iterable is equivalent to: for item in iterable: yield item but is more efficient. That's really all you need to know! From louisadencap at yahoo.com Tue Oct 11 19:40:31 2022 From: louisadencap at yahoo.com (LouisAden Capellupo) Date: Tue, 11 Oct 2022 16:40:31 -0700 Subject: How to fix Python error, The term '.../python.exe' is not recognized as the name of a cmdlet, function, script file, or operable program, in VS Code? Message-ID: <998337851.644732.1665531633363@yahoo.com> ???? Hi! I've just downloaded and installed Python 3.10.7 (64-bit) for Windows 10 from python.org. I'm quite new but, I've already downloaded and installed Visual Studio Code as well. I have included the two paths for python under User Variables.?C:\Users\It'sMeLil'Loui\AppData\Local\Programs\Python\Python310\Scripts\, and?C:\Users\It'sMeLil'Loui\AppData\Local\Programs\Python\Python310\. I verified that python is recognized in the Command Prompt and PowerShell and installed the necessary extensions for python in Visual Studio Code. I created a test python file in the directory of?D:\Projects\Python\Test\HelloWorld.py, and opened it in Visual Studio Code. I also restarted my laptop after all of this. Under the arrow used to run the code, I clicked "Run Code" (since I have Code Runner by Jun Han installed), and it worked just fine, displaying the output in the terminal. Code: print("Hello, world.") input("Press Enter to continue...") Output in Terminal when using Code Runner: Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. Try the new cross-platform PowerShell https://aka.ms/pscore6 PS D:\Projects\Python\Test> python -u "d:\Projects\Python\Test\HelloWorld.py" Hello, world. Press Enter to continue... PS D:\Projects\Python\Test> However, under the arrow to run code, when I click "Run Python File", I get this error message: Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. Output in Terminal when normally running it: Try the new cross-platform PowerShell https://aka.ms/pscore6 PS D:\Projects\Python\Test> & C:/Users/It'sMeLil'Loui/AppData/Local/Programs/Python/Python310/python.exe d:/Projects/Python/Test/HelloWorld.py & : The term 'C:/Users/ItsMeLilLoui/AppData/Local/Programs/Python/Python310/python.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:3 + & C:/Users/It'sMeLil'Loui/AppData/Local/Programs/Python/Python310/pyt ... +?? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ??? + CategoryInfo????????? : ObjectNotFound: (C:/Users/ItsMeL...n310/python.exe:String) [], CommandNotFoundException ??? + FullyQualifiedErrorId : CommandNotFoundException PS D:\Projects\Python\Test> ?????So basically, I get, "The term '...\python.exe' is not recognized as the name of a cmdlet, function, script, file, or operable program... At line: 1 char: 3." It works the first way I showed with Code Runner, but the second or original way doesn't work. What if I don't want to use Code Runner? Any help in fixing this problem would be greatly appreciated. Sorry if certain things are unclear as this is my first time using Python. Thanks, LouisAden Sent from Mail for Windows From eryksun at gmail.com Tue Oct 11 21:15:27 2022 From: eryksun at gmail.com (Eryk Sun) Date: Tue, 11 Oct 2022 20:15:27 -0500 Subject: How to fix Python error, The term '.../python.exe' is not recognized as the name of a cmdlet, function, script file, or operable program, in VS Code? In-Reply-To: <998337851.644732.1665531633363@yahoo.com> References: <998337851.644732.1665531633363@yahoo.com> Message-ID: On 10/11/22, LouisAden Capellupo via Python-list wrote: > Variables. C:\Users\It'sMeLil'Loui\AppData\Local\Programs\Python\Python310\Scripts\, > and C:\Users\It'sMeLil'Loui\AppData\Local\Programs\Python\Python310\. I suggest that you switch to a user account that doesn't have single quotes in the name. Using a name that contains single quotes is asking for trouble. In most command-line shells, which includes PowerShell (but not CMD), a literal (verbatim) string is contained by single quotes. The shell usually consumes the quote character if it's not escaped. See the following sections of the PowerShell documentation: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.2#single-quoted-strings https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.2#including-quote-characters-in-a-string From drsalists at gmail.com Tue Oct 11 22:46:21 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Tue, 11 Oct 2022 19:46:21 -0700 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: On Tue, Oct 11, 2022 at 12:48 PM SquidBits _ wrote: > Does anyone else think there should be a flatten () function, which just > turns a multi-dimensional list into a one-dimensional list in the order > it's in. e.g. > > [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > > I have had to flatten lists quite a few times and it's quite tedious to > type out. It feels like this should be something built in to python, anyone > else think this way? > I think the usual argument against putting something like this in the standard library (I hope it won't be built in), is that there are many ways to define "flatten". That is, should it only go one level deep? All the way to the bottom? n levels deep? Should it do something special with lists, dicts, tuples, sets? This looks like a nice URL on the topic: https://www.pythonpool.com/flatten-list-python/ From axy at declassed.art Tue Oct 11 23:36:08 2022 From: axy at declassed.art (Axy) Date: Wed, 12 Oct 2022 04:36:08 +0100 Subject: for -- else: what was the motivation? In-Reply-To: <00d201d8dc67$53905620$fab10260$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <00a901d8dc5c$719fce30$54df6a90$@gmail.com> <00d201d8dc67$53905620$fab10260$@gmail.com> Message-ID: <239c0121-3d51-57a2-c8d2-206ee02c47b7@declassed.art> On 10/10/2022 06:15, avi.e.gross at gmail.com wrote: > Chris, a short(er) answer to your addition below. > > I did not at first share your perception but maybe do now. If the argument > was that ELSE and other constructs like FINALLY or CATCH are horrible > because they follow other code and important things should be first, that is > a silly argument. You know, sometimes I'm of the same opinion, especially looking at "defer" efforts in Go. However, I wouldn't judge that in terms of mental capabilities. Every construct has some initial rationale but sometimes even best practices eventually become notorious. There are many point of views to every feature but in general features aren't divine and worth revising even this looks disparaging. Axy. From PythonList at DancesWithMice.info Wed Oct 12 01:19:15 2022 From: PythonList at DancesWithMice.info (dn) Date: Wed, 12 Oct 2022 18:19:15 +1300 Subject: Help, PyCharm fails to recognize my tab setting...See attached picture of the code. In-Reply-To: <2030144807.7310447.1665438501827@mail.yahoo.com> References: <2030144807.7310447.1665438501827.ref@mail.yahoo.com> <2030144807.7310447.1665438501827@mail.yahoo.com> Message-ID: <1dea2f11-755f-d054-dfd7-64b948e2b9d7@DancesWithMice.info> On 11/10/2022 10.48, Kevin M. Wilson via Python-list wrote: > C:\Users\kevin\PycharmProjects\Myfuturevalue\venv\Scripts\python.exe C:\Users\kevin\PycharmProjects\Myfuturevalue\FutureValueCal.py?? File "C:\Users\kevin\PycharmProjects\Myfuturevalue\FutureValueCal.py", line 31? ? elif (years > 50.0) or (years < 1.0) :? ? ^IndentationError: expected an indented block after 'if' statement on line 29 > Process finished with exit code 1 Indentation depends upon what went before, as well as what is being indented 'right now'. As you can see from the reproduction of the OP (above), any comment on formatting would be a guess. Please copy-paste the entire block of the if-statement and its nested suites... (this list will not pass-along images) -- Regards, =dn From antoon.pardon at vub.be Wed Oct 12 12:45:39 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Wed, 12 Oct 2022 18:45:39 +0200 Subject: flattening lists In-Reply-To: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> References: <10d193c8-0dbe-41c8-9c63-17e4c04f1c97n@googlegroups.com> Message-ID: <0ee80123-5f94-ac3f-3384-d9441c5a69c5@vub.be> Op 11/10/2022 om 21:32 schreef SquidBits _: > Does anyone else think there should be a flatten () function, which just turns a multi-dimensional list into a one-dimensional list in the order it's in. e.g. > > [[1,2,3],[4,5,6,7],[8,9]] becomes [1,2,3,4,5,6,7,8,9]. > > I have had to flatten lists quite a few times and it's quite tedious to type out. It feels like this should be something built in to python, anyone else think this way? Depending on what you exactly mean by "flatten", it already is easy to flatten a list in python: >>> lst = [[1,2,3],[4,5,6,7],[8,9]] >>> list(itertools.chain.from_iterable(lst)) [1, 2, 3, 4, 5, 6, 7, 8, 9] -- Antoon Pardon From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 00:00:08 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 05:00:08 +0100 Subject: Find the path of a shell command Message-ID: Hi! The simple question: How do I find the full path of a shell command (linux), i.e. how do I obtain the corresponding of, for example, "type rm" in command line? The reason: I have python program that launches a detached rm. It works pretty well until it is invoked by cron! I suspect that for cron we need to specify the full path. Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? What about other commands? Thanks for any comments/responses. Paulo From nospam at please.ty Wed Oct 12 01:11:56 2022 From: nospam at please.ty (jak) Date: Wed, 12 Oct 2022 07:11:56 +0200 Subject: Find the path of a shell command References: Message-ID: Il 12/10/2022 06:00, Paulo da Silva ha scritto: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > > Thanks for any comments/responses. > Paulo > I'm afraid you will have to look for the command in every path listed in the PATH environment variable. From jkn_gg at nicorp.f9.co.uk Wed Oct 12 03:40:38 2022 From: jkn_gg at nicorp.f9.co.uk (jkn) Date: Wed, 12 Oct 2022 00:40:38 -0700 (PDT) Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: > Il 12/10/2022 06:00, Paulo da Silva ha scritto: > > Hi! > > > > The simple question: How do I find the full path of a shell command > > (linux), i.e. how do I obtain the corresponding of, for example, > > "type rm" in command line? > > > > The reason: > > I have python program that launches a detached rm. It works pretty well > > until it is invoked by cron! I suspect that for cron we need to specify > > the full path. > > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > > What about other commands? > > > > Thanks for any comments/responses. > > Paulo > > > I'm afraid you will have to look for the command in every path listed in > the PATH environment variable. erm, or try 'which rm' ? From abdulhaseeb.azizi786 at gmail.com Wed Oct 12 03:51:11 2022 From: abdulhaseeb.azizi786 at gmail.com (Abdul Haseeb Azizi) Date: Wed, 12 Oct 2022 00:51:11 -0700 (PDT) Subject: Cannot import gdal in jupyter notebook In-Reply-To: References: Message-ID: On Tuesday, October 11, 2022 at 10:29:34 PM UTC+2, MRAB wrote: > On 2022-10-11 20:38, Thomas Passin wrote: > > On Windows, when I tried to install gdal using pip, it needed to compile > > part of it. I'm not set up with the Microsoft compiler and header > > files, so that failed. If you are on Windows, you will need to look for > > a binary wheel to install, or install and configure the compiler and > > header files. > > > The PyPI page at https://pypi.org/project/GDAL/ has this: > > """ > Conda > GDAL can be quite complex to build and install, particularly on Windows > and MacOS. Pre built binaries are provided for the conda system: > > https://docs.conda.io/en/latest/ > > By the conda-forge project: > > https://conda-forge.org/ > """ > > > On 10/11/2022 11:53 AM, Abdul Haseeb Azizi wrote: > >> Hi everyone, > >> I am new to python and I am trying to utilize this code "from osgeo import gdal". I installed python 3.10 and also I installed anaconda3 to solve this matter but I could not succeed. When I run that code I get the following error. > >> --------------------------------------------------------------------------- > >> ModuleNotFoundError Traceback (most recent call last) > >> Cell In [1], line 1 > >> ----> 1 from osgeo import gdal > >> > >> ModuleNotFoundError: No module named 'osgeo' > >> > >> I also tried to create anaconda environment and enter the following codes: > >> conda crate --name pygdal > >> conda activate pygdal > >> conda install -c conda-forge gdal > >> > >> I don't what is the problem. Any help is appreciated to solve this matter. > >> Looking forward to hear from you. > >> > >> with regards > >> Abdul > > Thanks a lot for your recommendations. As I mentioned before I installed conda and also created conda environment using the following codes: Step 1: Create conda environment conda create --name venv After creating the virtual environment, by default it will install some of the packages. Step 2: Installation of gdal conda install -c conda-forge gdal Step 3: Installation of ipykernel conda install -c anaconda ipykernel Step 4: Add ipykernel and run jupyternotebook python -m ipykernel install --user --name=venv jupyter notebook still I get the following error: %pip install gdal Requirement already satisfied: gdal in c:\users\abdul\anaconda3\lib\site-packages (3.4.1) Note: you may need to restart the kernel to use updated packages. from osgeo import gdal --------------------------------------------------------------------------- ImportError Traceback (most recent call last) File ~\anaconda3\lib\site-packages\osgeo\__init__.py:29, in swig_import_helper() 28 try: ---> 29 return importlib.import_module(mname) 30 except ImportError: File ~\anaconda3\lib\importlib\__init__.py:127, in import_module(name, package) 126 level += 1 --> 127 return _bootstrap._gcd_import(name[level:], package, level) File :1030, in _gcd_import(name, package, level) File :1007, in _find_and_load(name, import_) File :986, in _find_and_load_unlocked(name, import_) File :666, in _load_unlocked(spec) File :565, in module_from_spec(spec) File :1173, in create_module(self, spec) File :228, in _call_with_frames_removed(f, *args, **kwds) ImportError: DLL load failed while importing _gdal: The specified module could not be found. During handling of the above exception, another exception occurred: ImportError Traceback (most recent call last) Input In [1], in () ----> 1 from osgeo import gdal File ~\anaconda3\lib\site-packages\osgeo\__init__.py:45, in 41 raise ImportError(traceback_string + '\n' + msg) 42 return importlib.import_module('_gdal') ---> 45 _gdal = swig_import_helper() 46 del swig_import_helper 48 __version__ = _gdal.__version__ = _gdal.VersionInfo("RELEASE_NAME") File ~\anaconda3\lib\site-packages\osgeo\__init__.py:41, in swig_import_helper() 39 import traceback 40 traceback_string = ''.join(traceback.format_exception(*sys.exc_info())) ---> 41 raise ImportError(traceback_string + '\n' + msg) 42 return importlib.import_module('_gdal') ImportError: Traceback (most recent call last): File "C:\Users\abdul\anaconda3\lib\site-packages\osgeo\__init__.py", line 29, in swig_import_helper return importlib.import_module(mname) File "C:\Users\abdul\anaconda3\lib\importlib\__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1030, in _gcd_import File "", line 1007, in _find_and_load File "", line 986, in _find_and_load_unlocked File "", line 666, in _load_unlocked File "", line 565, in module_from_spec File "", line 1173, in create_module File "", line 228, in _call_with_frames_removed ImportError: DLL load failed while importing _gdal: The specified module could not be found. On Windows, with Python >= 3.8, DLLs are no longer imported from the PATH. If gdalXXX.dll is in the PATH, then set the USE_PATH_FOR_GDAL_PYTHON=YES environment variable to feed the PATH into os.add_dll_directory(). I hope you could look at the errors and guide me to solve this problem. with regards Abdul From nospam at please.ty Wed Oct 12 07:02:15 2022 From: nospam at please.ty (jak) Date: Wed, 12 Oct 2022 13:02:15 +0200 Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: Il 12/10/2022 09:40, jkn ha scritto: > On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: >> Il 12/10/2022 06:00, Paulo da Silva ha scritto: >>> Hi! >>> >>> The simple question: How do I find the full path of a shell command >>> (linux), i.e. how do I obtain the corresponding of, for example, >>> "type rm" in command line? >>> >>> The reason: >>> I have python program that launches a detached rm. It works pretty well >>> until it is invoked by cron! I suspect that for cron we need to specify >>> the full path. >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>> What about other commands? >>> >>> Thanks for any comments/responses. >>> Paulo >>> >> I'm afraid you will have to look for the command in every path listed in >> the PATH environment variable. > > erm, or try 'which rm' ? You might but if you don't know where the 'rm' command is, you will have the same difficulty in using 'which' Command. Do not you think? From cl at isbd.net Wed Oct 12 08:20:02 2022 From: cl at isbd.net (Chris Green) Date: Wed, 12 Oct 2022 13:20:02 +0100 Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: jak wrote: > Il 12/10/2022 09:40, jkn ha scritto: > > On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: > >> Il 12/10/2022 06:00, Paulo da Silva ha scritto: > >>> Hi! > >>> > >>> The simple question: How do I find the full path of a shell command > >>> (linux), i.e. how do I obtain the corresponding of, for example, > >>> "type rm" in command line? > >>> > >>> The reason: > >>> I have python program that launches a detached rm. It works pretty well > >>> until it is invoked by cron! I suspect that for cron we need to specify > >>> the full path. > >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > >>> What about other commands? > >>> > >>> Thanks for any comments/responses. > >>> Paulo > >>> > >> I'm afraid you will have to look for the command in every path listed in > >> the PATH environment variable. > > > > erm, or try 'which rm' ? > > You might but if you don't know where the 'rm' command is, you will have > the same difficulty in using 'which' command. Do not you think? > >From a command prompt use the bash built-in 'command' :- command -v rm ... and rm will just about always be in /usr/bin. -- Chris Green ? From nospam at please.ty Wed Oct 12 08:46:56 2022 From: nospam at please.ty (jak) Date: Wed, 12 Oct 2022 14:46:56 +0200 Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: Il 12/10/2022 14:20, Chris Green ha scritto: > jak wrote: >> Il 12/10/2022 09:40, jkn ha scritto: >>> On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: >>>> Il 12/10/2022 06:00, Paulo da Silva ha scritto: >>>>> Hi! >>>>> >>>>> The simple question: How do I find the full path of a shell command >>>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>>> "type rm" in command line? >>>>> >>>>> The reason: >>>>> I have python program that launches a detached rm. It works pretty well >>>>> until it is invoked by cron! I suspect that for cron we need to specify >>>>> the full path. >>>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>>> What about other commands? >>>>> >>>>> Thanks for any comments/responses. >>>>> Paulo >>>>> >>>> I'm afraid you will have to look for the command in every path listed in >>>> the PATH environment variable. >>> >>> erm, or try 'which rm' ? >> >> You might but if you don't know where the 'rm' command is, you will have >> the same difficulty in using 'which' command. Do not you think? >> > From a command prompt use the bash built-in 'command' :- > > command -v rm > > ... and rm will just about always be in /usr/bin. > ok but I didn't suggest a very complicated thing: for p in os.getenv('PATH').split(os.path.pathsep): if p: if os.path.isfile(os.path.join(p, 'rm')): print(f) From abdulhaseeb.azizi786 at gmail.com Wed Oct 12 09:18:10 2022 From: abdulhaseeb.azizi786 at gmail.com (Abdul Haseeb Azizi) Date: Wed, 12 Oct 2022 06:18:10 -0700 (PDT) Subject: Cannot import gdal in jupyter notebook In-Reply-To: References: Message-ID: On Wednesday, October 12, 2022 at 9:51:22 AM UTC+2, Abdul Haseeb Azizi wrote: > On Tuesday, October 11, 2022 at 10:29:34 PM UTC+2, MRAB wrote: > > On 2022-10-11 20:38, Thomas Passin wrote: > > > On Windows, when I tried to install gdal using pip, it needed to compile > > > part of it. I'm not set up with the Microsoft compiler and header > > > files, so that failed. If you are on Windows, you will need to look for > > > a binary wheel to install, or install and configure the compiler and > > > header files. > > > > > The PyPI page at https://pypi.org/project/GDAL/ has this: > > > > """ > > Conda > > GDAL can be quite complex to build and install, particularly on Windows > > and MacOS. Pre built binaries are provided for the conda system: > > > > https://docs.conda.io/en/latest/ > > > > By the conda-forge project: > > > > https://conda-forge.org/ > > """ > > > > > On 10/11/2022 11:53 AM, Abdul Haseeb Azizi wrote: > > >> Hi everyone, > > >> I am new to python and I am trying to utilize this code "from osgeo import gdal". I installed python 3.10 and also I installed anaconda3 to solve this matter but I could not succeed. When I run that code I get the following error. > > >> --------------------------------------------------------------------------- > > >> ModuleNotFoundError Traceback (most recent call last) > > >> Cell In [1], line 1 > > >> ----> 1 from osgeo import gdal > > >> > > >> ModuleNotFoundError: No module named 'osgeo' > > >> > > >> I also tried to create anaconda environment and enter the following codes: > > >> conda crate --name pygdal > > >> conda activate pygdal > > >> conda install -c conda-forge gdal > > >> > > >> I don't what is the problem. Any help is appreciated to solve this matter. > > >> Looking forward to hear from you. > > >> > > >> with regards > > >> Abdul > > > > Thanks a lot for your recommendations. > As I mentioned before I installed conda and also created conda environment using the following codes: > Step 1: Create conda environment > > conda create --name venv > > After creating the virtual environment, by default it will install some of the packages. > Step 2: Installation of gdal > conda install -c conda-forge gdal > Step 3: Installation of ipykernel > > conda install -c anaconda ipykernel > > Step 4: Add ipykernel and run jupyternotebook > > python -m ipykernel install --user --name=venv > jupyter notebook > > > still I get the following error: > > %pip install gdal > > Requirement already satisfied: gdal in c:\users\abdul\anaconda3\lib\site-packages (3.4.1) > Note: you may need to restart the kernel to use updated packages. > > from osgeo import gdal > > > --------------------------------------------------------------------------- > ImportError Traceback (most recent call last) > File ~\anaconda3\lib\site-packages\osgeo\__init__.py:29, in swig_import_helper() > 28 try: > ---> 29 return importlib.import_module(mname) > 30 except ImportError: > > File ~\anaconda3\lib\importlib\__init__.py:127, in import_module(name, package) > 126 level += 1 > --> 127 return _bootstrap._gcd_import(name[level:], package, level) > > File :1030, in _gcd_import(name, package, level) > > File :1007, in _find_and_load(name, import_) > > File :986, in _find_and_load_unlocked(name, import_) > > File :666, in _load_unlocked(spec) > > File :565, in module_from_spec(spec) > > File :1173, in create_module(self, spec) > > File :228, in _call_with_frames_removed(f, *args, **kwds) > > ImportError: DLL load failed while importing _gdal: The specified module could not be found. > > During handling of the above exception, another exception occurred: > > ImportError Traceback (most recent call last) > Input In [1], in () > ----> 1 from osgeo import gdal > File ~\anaconda3\lib\site-packages\osgeo\__init__.py:45, in > 41 raise ImportError(traceback_string + '\n' + msg) > 42 return importlib.import_module('_gdal') > ---> 45 _gdal = swig_import_helper() > 46 del swig_import_helper > 48 __version__ = _gdal.__version__ = _gdal.VersionInfo("RELEASE_NAME") > > File ~\anaconda3\lib\site-packages\osgeo\__init__.py:41, in swig_import_helper() > 39 import traceback > 40 traceback_string = ''.join(traceback.format_exception(*sys.exc_info())) > ---> 41 raise ImportError(traceback_string + '\n' + msg) > 42 return importlib.import_module('_gdal') > > ImportError: Traceback (most recent call last): > File "C:\Users\abdul\anaconda3\lib\site-packages\osgeo\__init__.py", line 29, in swig_import_helper > return importlib.import_module(mname) > File "C:\Users\abdul\anaconda3\lib\importlib\__init__.py", line 127, in import_module > return _bootstrap._gcd_import(name[level:], package, level) > File "", line 1030, in _gcd_import > File "", line 1007, in _find_and_load > File "", line 986, in _find_and_load_unlocked > File "", line 666, in _load_unlocked > File "", line 565, in module_from_spec > File "", line 1173, in create_module > File "", line 228, in _call_with_frames_removed > ImportError: DLL load failed while importing _gdal: The specified module could not be found. > > On Windows, with Python >= 3.8, DLLs are no longer imported from the PATH. > If gdalXXX.dll is in the PATH, then set the USE_PATH_FOR_GDAL_PYTHON=YES environment variable > to feed the PATH into os.add_dll_directory(). > > I hope you could look at the errors and guide me to solve this problem. > > with regards > Abdul Hi all, I followed the instructions given in the following link and I could install gdal and it works perfectly now. In case this might be of use for anyone of you. https://www.quora.com/How-do-I-install-gdal-in-PyCharm thanks From michael.stemper at gmail.com Wed Oct 12 10:38:49 2022 From: michael.stemper at gmail.com (Michael F. Stemper) Date: Wed, 12 Oct 2022 09:38:49 -0500 Subject: Find the path of a shell command In-Reply-To: References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: On 12/10/2022 07.20, Chris Green wrote: > jak wrote: >> Il 12/10/2022 09:40, jkn ha scritto: >>> On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: >>>> I'm afraid you will have to look for the command in every path listed in >>>> the PATH environment variable. >>> >>> erm, or try 'which rm' ? >> >> You might but if you don't know where the 'rm' command is, you will have >> the same difficulty in using 'which' command. Do not you think? > From a command prompt use the bash built-in 'command' :- > > command -v rm > > ... and rm will just about always be in /usr/bin. On two different versions of Ubuntu, it's in /bin. -- Michael F. Stemper Psalm 94:3-6 From jon+usenet at unequivocal.eu Wed Oct 12 11:08:32 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 15:08:32 -0000 (UTC) Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: On 2022-10-12, Michael F. Stemper wrote: > On 12/10/2022 07.20, Chris Green wrote: >> ... and rm will just about always be in /usr/bin. > > On two different versions of Ubuntu, it's in /bin. It will almost always be in /bin in any Unix or Unix-like system, because it's one of the fundamental utilities that may be vital in fixing the system when it's booted in single-user mode and /usr may not be available. Also, the Filesystem Hierarchy Standard *requires* it to be in /bin. Having said that, nothing requires it not to be elsewhere *as well*, and in Ubuntu and other Linux systems it is in /usr/bin too. And because PATH for non-root users will usually contain /usr/bin before /bin (or indeed may not contain /bin at all), 'command -v rm' or 'which rm' will usually list the version of rm that is in /usr/bin. e.g. on Amazon Linux: $ which rm /usr/bin/rm $ sudo which rm /bin/rm From cl at isbd.net Wed Oct 12 11:06:35 2022 From: cl at isbd.net (Chris Green) Date: Wed, 12 Oct 2022 16:06:35 +0100 Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: Michael F. Stemper wrote: > On 12/10/2022 07.20, Chris Green wrote: > > jak wrote: > >> Il 12/10/2022 09:40, jkn ha scritto: > >>> On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: > > >>>> I'm afraid you will have to look for the command in every path listed in > >>>> the PATH environment variable. > >>> > >>> erm, or try 'which rm' ? > >> > >> You might but if you don't know where the 'rm' command is, you will have > >> the same difficulty in using 'which' command. Do not you think? > > From a command prompt use the bash built-in 'command' :- > > > > command -v rm > > > > ... and rm will just about always be in /usr/bin. > > On two different versions of Ubuntu, it's in /bin. > I think you'll find it's in both /bin and /usr/bin, usually /usr/bin is earlier in the path so /usr/bin/rm is the one that will normally be found first. It's only in /bin/rm in case one has a system which mounts /bin separately and earlier in the boot sequence and rm is one of the commands needed early on. -- Chris Green ? From wlfraed at ix.netcom.com Wed Oct 12 12:12:18 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 12 Oct 2022 12:12:18 -0400 Subject: How to fix Python error, The term '.../python.exe' is not recognized as the name of a cmdlet, function, script file, or operable program, in VS Code? References: <998337851.644732.1665531633363@yahoo.com> Message-ID: On Tue, 11 Oct 2022 16:40:31 -0700, LouisAden Capellupo declaimed the following: >?????So basically, I get, "The term '...\python.exe' is not recognized as the name of a cmdlet, function, script, file, or operable program... At line: 1 char: 3." It works the first way I showed with Code Runner, but the second or original way doesn't work. What if I don't want to use Code Runner? Any help in fixing this problem would be greatly appreciated. Sorry if certain things are unclear as this is my first time using Python. > What happens if you change the system to use the "command" shell INSTEAD OF PowerShell? PowerShell may not honor the same environment variables. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 12:43:18 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 17:43:18 +0100 Subject: Find the path of a shell command References: Message-ID: ?s 17:22 de 12/10/22, Tilmann Hentze escreveu: > Paulo da Silva schrieb: >> I have python program that launches a detached rm. It works pretty well >> until it is invoked by cron! I suspect that for cron we need to specify >> the full path. > > Probably you could use os.unlink[1] with no problem. No, because I need to launch several rm's that keep running after the script ends. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 12:49:40 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 17:49:40 +0100 Subject: Find the path of a shell command References: Message-ID: ?s 05:00 de 12/10/22, Paulo da Silva escreveu: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > Thank you all who have responded so far. I think that the the suggestion of searching the PATH env seems the best. Another thing that I thought of is that of the 'which', but, to avoid the mentioned recurrent problem of not knowing where 'which' is I would use 'type' instead. 'type' is a bash (sh?) command. Thanks Paulo From pfeiffer at cs.nmsu.edu Wed Oct 12 13:41:07 2022 From: pfeiffer at cs.nmsu.edu (Joe Pfeiffer) Date: Wed, 12 Oct 2022 11:41:07 -0600 Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: <1bsfjtndn0.fsf@pfeifferfamily.net> Jon Ribbens writes: > On 2022-10-12, Michael F. Stemper wrote: >> On 12/10/2022 07.20, Chris Green wrote: >>> ... and rm will just about always be in /usr/bin. >> >> On two different versions of Ubuntu, it's in /bin. > > It will almost always be in /bin in any Unix or Unix-like system, > because it's one of the fundamental utilities that may be vital in > fixing the system when it's booted in single-user mode and /usr may > not be available. Also, the Filesystem Hierarchy Standard *requires* > it to be in /bin. > > Having said that, nothing requires it not to be elsewhere *as well*, > and in Ubuntu and other Linux systems it is in /usr/bin too. And because > PATH for non-root users will usually contain /usr/bin before /bin (or > indeed may not contain /bin at all), 'command -v rm' or 'which rm' will > usually list the version of rm that is in /usr/bin. > > e.g. on Amazon Linux: > > $ which rm > /usr/bin/rm > $ sudo which rm > /bin/rm Have some major Linux distributions not done usrmerge yet? For any that have, /bin is a symbolic link to /usr/bin From kirill.ratkin at devoteam.com Wed Oct 12 05:20:17 2022 From: kirill.ratkin at devoteam.com (Kirill Ratkin) Date: Wed, 12 Oct 2022 12:20:17 +0300 Subject: Fail 3.10.8 version installation on Windows 11 21H2 Message-ID: <94974f11-16dd-deb6-2e2c-8a777354bb40@devoteam.com> Hi All, Do anyone face issue like in log below? I got last installer (3.10.8) and try to install it 'for all users' with downloading precompiled (pdb) files. And installation fails saying permission error. Installer says downloading error in the log. I repeated it three times with same result Just to test I got previous version (3.10.6) and it is installed without any errors with same installer settings. -------------------- begin here -------- part of installer log file --------------------------- [183C:19E4][2022-10-12T12:01:23]e000: Error 0x80070005: Failed attempt to download URL: 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' [183C:19E4][2022-10-12T12:01:23]w343: Prompt for source of package: core_AllUsers_pdb, payload: core_AllUsers_pdb, path: C:\Users\Kirill\Downloads\core_pdb.msi [183C:19E4][2022-10-12T12:01:26]i338: Acquiring package: core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi [183C:19E4][2022-10-12T12:01:26]e000: Error 0x80070005: Failed attempt to download URL: 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' [183C:19E4][2022-10-12T12:01:26]w343: Prompt for source of package: core_AllUsers_pdb, payload: core_AllUsers_pdb, path: C:\Users\Kirill\Downloads\core_pdb.msi [183C:19E4][2022-10-12T12:01:29]i338: Acquiring package: core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi [183C:19E4][2022-10-12T12:01:29]e000: Error 0x80070005: Failed attempt to download URL: 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' [183C:19E4][2022-10-12T12:01:29]w343: Prompt for source of package: core_AllUsers_pdb, payload: core_AllUsers_pdb, path: C:\Users\Kirill\Downloads\core_pdb.msi [183C:19E4][2022-10-12T12:01:32]i338: Acquiring package: core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi [183C:19E4][2022-10-12T12:01:32]e000: Error 0x80070005: Failed attempt to download URL: 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' [183C:19E4][2022-10-12T12:01:32]e000: Error 0x80070005: Failed to acquire payload from: 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to working path: 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' [183C:19E4][2022-10-12T12:01:32]e313: Failed to acquire payload: core_AllUsers_pdb to working path: C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb, error: 0x80070005. [08CC:3570][2022-10-12T12:01:32]i351: Removing cached package: core_AllUsers, from path: C:\ProgramData\Package Cache\{6463E43B-54B1-4407-818D-DD90D11CDD06}v3.10.8150.0\ [183C:313C][2022-10-12T12:01:32]e000: Error 0x80070005: Cache thread exited unexpectedly. -------------------- end here -------- part of installer log file --------------------------- From jon+usenet at unequivocal.eu Wed Oct 12 14:08:18 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 18:08:18 -0000 (UTC) Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> <1bsfjtndn0.fsf@pfeifferfamily.net> Message-ID: On 2022-10-12, Joe Pfeiffer wrote: > Jon Ribbens writes: > >> On 2022-10-12, Michael F. Stemper wrote: >>> On 12/10/2022 07.20, Chris Green wrote: >>>> ... and rm will just about always be in /usr/bin. >>> >>> On two different versions of Ubuntu, it's in /bin. >> >> It will almost always be in /bin in any Unix or Unix-like system, >> because it's one of the fundamental utilities that may be vital in >> fixing the system when it's booted in single-user mode and /usr may >> not be available. Also, the Filesystem Hierarchy Standard *requires* >> it to be in /bin. >> >> Having said that, nothing requires it not to be elsewhere *as well*, >> and in Ubuntu and other Linux systems it is in /usr/bin too. And because >> PATH for non-root users will usually contain /usr/bin before /bin (or >> indeed may not contain /bin at all), 'command -v rm' or 'which rm' will >> usually list the version of rm that is in /usr/bin. >> >> e.g. on Amazon Linux: >> >> $ which rm >> /usr/bin/rm >> $ sudo which rm >> /bin/rm > > Have some major Linux distributions not done usrmerge yet? For any that > have, /bin is a symbolic link to /usr/bin I have immediate access to CentOS 7, Ubuntu 20, and Amazon Linux 2, and none of those have done that. From python at mrabarnett.plus.com Wed Oct 12 14:19:42 2022 From: python at mrabarnett.plus.com (MRAB) Date: Wed, 12 Oct 2022 19:19:42 +0100 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <91b52ffc-4ed1-b1f5-1e28-02db0f7933f1@mrabarnett.plus.com> On 2022-10-12 06:11, jak wrote: > Il 12/10/2022 06:00, Paulo da Silva ha scritto: >> Hi! >> >> The simple question: How do I find the full path of a shell command >> (linux), i.e. how do I obtain the corresponding of, for example, >> "type rm" in command line? >> >> The reason: >> I have python program that launches a detached rm. It works pretty well >> until it is invoked by cron! I suspect that for cron we need to specify >> the full path. >> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >> What about other commands? >> >> Thanks for any comments/responses. >> Paulo >> > > I'm afraid you will have to look for the command in every path listed in > the PATH environment variable. > Isn't that what the "whereis" command does? From jon+usenet at unequivocal.eu Wed Oct 12 14:14:40 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 18:14:40 -0000 (UTC) Subject: Find the path of a shell command References: Message-ID: On 2022-10-12, Paulo da Silva wrote: > ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >> Hi! >> >> The simple question: How do I find the full path of a shell command >> (linux), i.e. how do I obtain the corresponding of, for example, >> "type rm" in command line? >> >> The reason: >> I have python program that launches a detached rm. It works pretty well >> until it is invoked by cron! I suspect that for cron we need to specify >> the full path. >> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >> What about other commands? >> > Thank you all who have responded so far. > I think that the the suggestion of searching the PATH env seems the best. > Another thing that I thought of is that of the 'which', but, to avoid > the mentioned recurrent problem of not knowing where 'which' is I would > use 'type' instead. 'type' is a bash (sh?) command. If you're using subprocess.run / subprocess.Popen then the computer is *already* searching PATH for you. Your problem must be that your cron job is being run without PATH being set, perhaps you just need to edit your crontab to set PATH to something sensible. Or just hard-code your program to run '/bin/rm' explicitly, which should always work (unless you're on Windows, of course!) From jkn_gg at nicorp.f9.co.uk Wed Oct 12 14:33:35 2022 From: jkn_gg at nicorp.f9.co.uk (jkn) Date: Wed, 12 Oct 2022 11:33:35 -0700 (PDT) Subject: Find the path of a shell command In-Reply-To: References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: On Wednesday, October 12, 2022 at 12:07:36 PM UTC+1, jak wrote: > Il 12/10/2022 09:40, jkn ha scritto: > > On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: > >> Il 12/10/2022 06:00, Paulo da Silva ha scritto: > >>> Hi! > >>> > >>> The simple question: How do I find the full path of a shell command > >>> (linux), i.e. how do I obtain the corresponding of, for example, > >>> "type rm" in command line? > >>> > >>> The reason: > >>> I have python program that launches a detached rm. It works pretty well > >>> until it is invoked by cron! I suspect that for cron we need to specify > >>> the full path. > >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > >>> What about other commands? > >>> > >>> Thanks for any comments/responses. > >>> Paulo > >>> > >> I'm afraid you will have to look for the command in every path listed in > >> the PATH environment variable. > > > > erm, or try 'which rm' ? > You might but if you don't know where the 'rm' command is, you will have > the same difficulty in using 'which' Command. Do not you think? I don't need to know where the rm command is in order to use the which command. I *was* (knowingly and deliberately) assuming that you have a semi-reasonably working system, and that your question meant "given command X, how do I find where the executable X is on my system?". Sounds like you want to make less assumptions than that. Fine. but probably best to be clear about your assumptions up front. J^n From antoon.pardon at vub.be Wed Oct 12 15:09:58 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Wed, 12 Oct 2022 21:09:58 +0200 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <7154a197-13f8-c20f-da36-830e16fd8c22@vub.be> Op 12/10/2022 om 18:49 schreef Paulo da Silva: > ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >> Hi! >> >> The simple question: How do I find the full path of a shell command >> (linux), i.e. how do I obtain the corresponding of, for example, >> "type rm" in command line? >> >> The reason: >> I have python program that launches a detached rm. It works pretty >> well until it is invoked by cron! I suspect that for cron we need to >> specify the full path. >> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >> What about other commands? >> > Thank you all who have responded so far. > I think that the the suggestion of searching the PATH env seems the best. I fear that won't work. If it doesn't work in cron, that probably means, PATH is not set properly in your cron environment. And if PATH is not set properly, searching it explicitely won't work either. If rm works when evoked directly in a cron script but not via a python script, you may need to export the PATH in your cron script. -- Antoon Pardon From 2QdxY4RzWzUUiLuE at potatochowder.com Wed Oct 12 15:16:02 2022 From: 2QdxY4RzWzUUiLuE at potatochowder.com (2QdxY4RzWzUUiLuE at potatochowder.com) Date: Wed, 12 Oct 2022 15:16:02 -0400 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 2022-10-12 at 17:43:18 +0100, Paulo da Silva wrote: > ?s 17:22 de 12/10/22, Tilmann Hentze escreveu: > > Paulo da Silva schrieb: > > > I have python program that launches a detached rm. It works pretty well > > > until it is invoked by cron! I suspect that for cron we need to specify > > > the full path. > > > > Probably you could use os.unlink[1] with no problem. > No, because I need to launch several rm's that keep running after the script > ends. rm doesn't take that long. Why are you detaching them? (I'm not debating your point about cron.) From grant.b.edwards at gmail.com Wed Oct 12 17:02:04 2022 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Wed, 12 Oct 2022 14:02:04 -0700 (PDT) Subject: Find the path of a shell command References: Message-ID: <63472b4c.050a0220.b431f.0dde@mx.google.com> On 2022-10-12, 2QdxY4RzWzUUiLuE at potatochowder.com <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > On 2022-10-12 at 17:43:18 +0100, Paulo da Silva wrote: >> >> > Probably you could use os.unlink[1] with no problem. >> >> No, because I need to launch several rm's that keep running after the script >> ends. > > rm doesn't take that long. Recursive ones can take a long time. From gweatherby at uchc.edu Wed Oct 12 17:11:48 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Wed, 12 Oct 2022 21:11:48 +0000 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: As did I. tree = ET.parse(lfile) for child in tree.getroot(): if child.tag == 'server': break else: raise ValueError(f"server tag not found in {lfile}") I think there are other places I could be using it, but honestly I tend to forget it?s available. From: Python-list on behalf of Stefan Ram Date: Wednesday, October 12, 2022 at 2:22 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** Axy writes: >So, seriously, why they needed else if the following pieces produce same >result? Does anyone know or remember their motivation? Just wrote code wherein I used "else"! This: import locale for name in( 'de', 'de_DE', 'deu_deu', 'deu', 'German', 'Deutsch' ): try: locale.setlocale( locale.LC_ALL, name ); break except locale.Error: pass else: print( "Programm kann deutsche Schreibweise nicht einrichten." ) . -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!iyDac-XjNlj78G0XwNzZ-FEHyuCZIy33n3cI9MUDM_FnEdR04mSQ5Ln0OA1ETUNloyH24iY9meNHVdixLgWRYL8$ From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 16:45:54 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 21:45:54 +0100 Subject: Find the path of a shell command References: Message-ID: ?s 20:16 de 12/10/22, 2QdxY4RzWzUUiLuE at potatochowder.com escreveu: > On 2022-10-12 at 17:43:18 +0100, > Paulo da Silva wrote: > >> ?s 17:22 de 12/10/22, Tilmann Hentze escreveu: >>> Paulo da Silva schrieb: >>>> I have python program that launches a detached rm. It works pretty well >>>> until it is invoked by cron! I suspect that for cron we need to specify >>>> the full path. >>> >>> Probably you could use os.unlink[1] with no problem. >> No, because I need to launch several rm's that keep running after the script >> ends. > > rm doesn't take that long. Why are you detaching them? Because the use of "rm -rf" here is to remove full dirs, mostly in external drives, each reaching more than hundreds thousand files. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 16:51:39 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 21:51:39 +0100 Subject: Find the path of a shell command References: Message-ID: ?s 19:14 de 12/10/22, Jon Ribbens escreveu: > On 2022-10-12, Paulo da Silva wrote: >> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>> Hi! >>> >>> The simple question: How do I find the full path of a shell command >>> (linux), i.e. how do I obtain the corresponding of, for example, >>> "type rm" in command line? >>> >>> The reason: >>> I have python program that launches a detached rm. It works pretty well >>> until it is invoked by cron! I suspect that for cron we need to specify >>> the full path. >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>> What about other commands? >>> >> Thank you all who have responded so far. >> I think that the the suggestion of searching the PATH env seems the best. >> Another thing that I thought of is that of the 'which', but, to avoid >> the mentioned recurrent problem of not knowing where 'which' is I would >> use 'type' instead. 'type' is a bash (sh?) command. > > If you're using subprocess.run / subprocess.Popen then the computer is > *already* searching PATH for you. Yes, and it works out of cron. > Your problem must be that your cron > job is being run without PATH being set, perhaps you just need to edit > your crontab to set PATH to something sensible. I could do that, but I am using /etc/cron.* for convenience. > Or just hard-code your > program to run '/bin/rm' explicitly, which should always work (unless > you're on Windows, of course!) It can also be in /bin, at least. A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer searching thru PATH env. It only needs to do that once. From jon+usenet at unequivocal.eu Wed Oct 12 16:54:19 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 20:54:19 -0000 (UTC) Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> <1bsfjtndn0.fsf@pfeifferfamily.net> Message-ID: On 2022-10-12, Jon Ribbens wrote: > On 2022-10-12, Joe Pfeiffer wrote: >> Jon Ribbens writes: >> >>> On 2022-10-12, Michael F. Stemper wrote: >>>> On 12/10/2022 07.20, Chris Green wrote: >>>>> ... and rm will just about always be in /usr/bin. >>>> >>>> On two different versions of Ubuntu, it's in /bin. >>> >>> It will almost always be in /bin in any Unix or Unix-like system, >>> because it's one of the fundamental utilities that may be vital in >>> fixing the system when it's booted in single-user mode and /usr may >>> not be available. Also, the Filesystem Hierarchy Standard *requires* >>> it to be in /bin. >>> >>> Having said that, nothing requires it not to be elsewhere *as well*, >>> and in Ubuntu and other Linux systems it is in /usr/bin too. And because >>> PATH for non-root users will usually contain /usr/bin before /bin (or >>> indeed may not contain /bin at all), 'command -v rm' or 'which rm' will >>> usually list the version of rm that is in /usr/bin. >>> >>> e.g. on Amazon Linux: >>> >>> $ which rm >>> /usr/bin/rm >>> $ sudo which rm >>> /bin/rm >> >> Have some major Linux distributions not done usrmerge yet? For any that >> have, /bin is a symbolic link to /usr/bin > > I have immediate access to CentOS 7, Ubuntu 20, and Amazon Linux 2, > and none of those have done that. Sorry, in fact they have done that - I misread your comment as being that they had symlinked the executables not the directories. This seems quite an unwise move to me but presumably they've thought it through. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 16:56:16 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 21:56:16 +0100 Subject: Find the path of a shell command References: <7154a197-13f8-c20f-da36-830e16fd8c22@vub.be> Message-ID: ?s 20:09 de 12/10/22, Antoon Pardon escreveu: > > > Op 12/10/2022 om 18:49 schreef Paulo da Silva: >> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>> Hi! >>> >>> The simple question: How do I find the full path of a shell command >>> (linux), i.e. how do I obtain the corresponding of, for example, >>> "type rm" in command line? >>> >>> The reason: >>> I have python program that launches a detached rm. It works pretty >>> well until it is invoked by cron! I suspect that for cron we need to >>> specify the full path. >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>> What about other commands? >>> >> Thank you all who have responded so far. >> I think that the the suggestion of searching the PATH env seems the best. > > I fear that won't work. > > If it doesn't work in cron, that probably means, PATH is not set > properly in your cron environment. And if PATH is not set properly, > searching it explicitely won't work either. > It seems you are right :-( I didn't think of that! Does 'type' bash command work? I don't know how bash 'type' works. I need to do some tests. Thanks Paulo From nospam at please.ty Wed Oct 12 17:14:46 2022 From: nospam at please.ty (jak) Date: Wed, 12 Oct 2022 23:14:46 +0200 Subject: Find the path of a shell command References: <91b52ffc-4ed1-b1f5-1e28-02db0f7933f1@mrabarnett.plus.com> Message-ID: Il 12/10/2022 20:19, MRAB ha scritto: > On 2022-10-12 06:11, jak wrote: >> Il 12/10/2022 06:00, Paulo da Silva ha scritto: >>> Hi! >>> >>> The simple question: How do I find the full path of a shell command >>> (linux), i.e. how do I obtain the corresponding of, for example, >>> "type rm" in command line? >>> >>> The reason: >>> I have python program that launches a detached rm. It works pretty >>> well until it is invoked by cron! I suspect that for cron we need to >>> specify the full path. >>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>> What about other commands? >>> >>> Thanks for any comments/responses. >>> Paulo >>> >> >> I'm afraid you will have to look for the command in every path listed in >> the PATH environment variable. >> > Isn't that what the "whereis" command does? "whereis" does more than the OP wants. A suitable command could be "which" but if the OP is in a context where he needs to know the path of the command, then it will have the same problem with "whereis" or "which". In any case they would be a few lines of Python: import os def which(c): for p in os.getenv('PATH').split(os.path.pathsep): if p and os.path.isfile(f := os.path.join(p, c)): return f return '' cmd = 'explorer.exe' cmdp = which(cmd) if cmdp: print("found:", cmdp) else: print("not found" From jon+usenet at unequivocal.eu Wed Oct 12 17:17:29 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 21:17:29 -0000 (UTC) Subject: Find the path of a shell command References: Message-ID: On 2022-10-12, Paulo da Silva wrote: > ?s 19:14 de 12/10/22, Jon Ribbens escreveu: >> On 2022-10-12, Paulo da Silva wrote: >>> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>>> Hi! >>>> >>>> The simple question: How do I find the full path of a shell command >>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>> "type rm" in command line? >>>> >>>> The reason: >>>> I have python program that launches a detached rm. It works pretty well >>>> until it is invoked by cron! I suspect that for cron we need to specify >>>> the full path. >>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>> What about other commands? >>>> >>> Thank you all who have responded so far. >>> I think that the the suggestion of searching the PATH env seems the best. >>> Another thing that I thought of is that of the 'which', but, to avoid >>> the mentioned recurrent problem of not knowing where 'which' is I would >>> use 'type' instead. 'type' is a bash (sh?) command. >> >> If you're using subprocess.run / subprocess.Popen then the computer is >> *already* searching PATH for you. > Yes, and it works out of cron. >> Your problem must be that your cron >> job is being run without PATH being set, perhaps you just need to edit >> your crontab to set PATH to something sensible. > I could do that, but I am using /etc/cron.* for convenience. > >> Or just hard-code your >> program to run '/bin/rm' explicitly, which should always work (unless >> you're on Windows, of course!) > It can also be in /bin, at least. I assume you mean /usr/bin. But it doesn't matter. As already discussed, even if 'rm' is in /usr/bin, it will be in /bin as well (or /usr/bin and /bin will be symlinks to the same place). > A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer > searching thru PATH env. It only needs to do that once. I cannot think of any situation in which that will help you. But if for some reason you really want to do that, you can use the shutil.which() function from the standard library: >>> import shutil >>> shutil.which('rm') '/usr/bin/rm' From gweatherby at uchc.edu Wed Oct 12 17:25:54 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Wed, 12 Oct 2022 21:25:54 +0000 Subject: Find the path of a shell command In-Reply-To: <63472b4c.050a0220.b431f.0dde@mx.google.com> References: <63472b4c.050a0220.b431f.0dde@mx.google.com> Message-ID: Some thoughts / notes: 1. On our Ubuntu-Server 20.04.3 based systems, /bin/rm and /usr/bin/rm are hard links to the same file. 2. Put the following in a bash script and run it from cron. Then you can see what your environment is. Mine has PATH=/usr/bin:/bin in it. #!/bin/bash env > /tmp/env$$ 3. You can background Python just as well as you can a separate rm invocation. if os.fork() == 0: os.unlink(?.) From: Python-list on behalf of Grant Edwards Date: Wednesday, October 12, 2022 at 5:03 PM To: python-list at python.org Subject: Re: Find the path of a shell command *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** On 2022-10-12, 2QdxY4RzWzUUiLuE at potatochowder.com <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: > On 2022-10-12 at 17:43:18 +0100, Paulo da Silva wrote: >> >> > Probably you could use os.unlink[1] with no problem. >> >> No, because I need to launch several rm's that keep running after the script >> ends. > > rm doesn't take that long. Recursive ones can take a long time. -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ny8-fSGJEE3wk-Yq188xuT5aamgIUVI6SJQHkNaxMp11JelflHEJ2SQcYqqSC1s8pxkifVVdFyeEcbSv1ZJlqoaxuG_m$ From list1 at tompassin.net Wed Oct 12 17:27:31 2022 From: list1 at tompassin.net (Thomas Passin) Date: Wed, 12 Oct 2022 17:27:31 -0400 Subject: Fail 3.10.8 version installation on Windows 11 21H2 In-Reply-To: <94974f11-16dd-deb6-2e2c-8a777354bb40@devoteam.com> References: <94974f11-16dd-deb6-2e2c-8a777354bb40@devoteam.com> Message-ID: <3da1b02b-6f16-6d63-37a2-f41e018cba46@tompassin.net> You probably need to install from an administrator account to install for all users. On 10/12/2022 5:20 AM, Kirill Ratkin via Python-list wrote: > Hi All, > > > Do anyone face issue like in log below? > > I got last installer (3.10.8) and try to install it 'for all users' with > downloading precompiled (pdb) files. > > And installation fails saying permission error. > > Installer says downloading error in the log. > > > I repeated it three times with same result > > > > Just to test I got previous version (3.10.6) and it is installed without > any errors with same installer settings. > > > -------------------- begin here -------- part of installer log file > --------------------------- > > [183C:19E4][2022-10-12T12:01:23]e000: Error 0x80070005: Failed attempt > to download URL: > 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: > 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' > [183C:19E4][2022-10-12T12:01:23]w343: Prompt for source of package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, path: > C:\Users\Kirill\Downloads\core_pdb.msi > [183C:19E4][2022-10-12T12:01:26]i338: Acquiring package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: > https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi > [183C:19E4][2022-10-12T12:01:26]e000: Error 0x80070005: Failed attempt > to download URL: > 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: > 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' > [183C:19E4][2022-10-12T12:01:26]w343: Prompt for source of package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, path: > C:\Users\Kirill\Downloads\core_pdb.msi > [183C:19E4][2022-10-12T12:01:29]i338: Acquiring package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: > https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi > [183C:19E4][2022-10-12T12:01:29]e000: Error 0x80070005: Failed attempt > to download URL: > 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: > 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' > [183C:19E4][2022-10-12T12:01:29]w343: Prompt for source of package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, path: > C:\Users\Kirill\Downloads\core_pdb.msi > [183C:19E4][2022-10-12T12:01:32]i338: Acquiring package: > core_AllUsers_pdb, payload: core_AllUsers_pdb, download from: > https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi > [183C:19E4][2022-10-12T12:01:32]e000: Error 0x80070005: Failed attempt > to download URL: > 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to: > 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' > [183C:19E4][2022-10-12T12:01:32]e000: Error 0x80070005: Failed to > acquire payload from: > 'https://www.python.org/ftp/python/3.10.8/amd64/core_pdb.msi' to working > path: > 'C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb' > [183C:19E4][2022-10-12T12:01:32]e313: Failed to acquire payload: > core_AllUsers_pdb to working path: > C:\Users\Kirill\AppData\Local\Temp\{93FCA30B-7B82-4BF0-B911-5223F0E6A053}\core_AllUsers_pdb, error: 0x80070005. > [08CC:3570][2022-10-12T12:01:32]i351: Removing cached package: > core_AllUsers, from path: C:\ProgramData\Package > Cache\{6463E43B-54B1-4407-818D-DD90D11CDD06}v3.10.8150.0\ > [183C:313C][2022-10-12T12:01:32]e000: Error 0x80070005: Cache thread > exited unexpectedly. > > -------------------- end here -------- part of installer log file > --------------------------- > > From list1 at tompassin.net Wed Oct 12 17:28:17 2022 From: list1 at tompassin.net (Thomas Passin) Date: Wed, 12 Oct 2022 17:28:17 -0400 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <5fd2939c-dcdf-7b6b-3f51-2abdd8def3ad@tompassin.net> On 10/12/2022 12:00 AM, Paulo da Silva wrote: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > > Thanks for any comments/responses. > Paulo > Python has a command that usually does the job: import shutil, os executable_path = shutil.which(exename, os.X_OK) If you know that the executable you want is on some non-standard path, you can or them together: executable_path = shutil.which(exename, os.X_OK)\ or shutil.which(exename, os.X_OK, other_path) Presumably the shutil command uses which behind the scenes, but that doesn't matter. Now you can include this location when you run the executable from Python. If you need to run a system command from a batch file and not from Python, you will either need to have the right path in effect when the batch file is run, or manually include the full path to the file in the batch file. BTW, on Linux Mint, which is derived from Ubuntu and Debian, rm is at $ which rm /bin/rm From cs at cskk.id.au Wed Oct 12 17:43:18 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 13 Oct 2022 08:43:18 +1100 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 12Oct2022 17:49, Paulo da Silva wrote: >?s 05:00 de 12/10/22, Paulo da Silva escreveu: >I think that the the suggestion of searching the PATH env seems the >best. I just want to note that you want to not just check for existence of the path, but that it is executable (permissionwise). You want to use `X_OK` with the `os.access` function: https://docs.python.org/3/library/os.html#os.access Also notice that the `shutil` module has a `which()` function: https://docs.python.org/3/library/shutil.html#shutil.which >Another thing that I thought of is that of the 'which', but, to avoid >the mentioned recurrent problem of not knowing where 'which' is I >would use 'type' instead. `which` will almost always be in `/usr/bin` (or `/bin` on some systems I suppose). But do you need to know where `which` is? If you're invoking it instead of search `$PATH`, the normal executtion stuff itself search `$PATH`, an will find `which` for you :-) >'type' is a bash (sh?) command. Yeah. Bash, ksh etc have `type`. It is a builtin, shich can see if a command word you give it is a shell alias or function or builtin or externally executed command. As you'd imagine, an external executable like `which` has no access to the internals of your shell, and can only look for executables. Cheers, Cameron Simpson From gweatherby at uchc.edu Wed Oct 12 17:44:19 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Wed, 12 Oct 2022 21:44:19 +0000 Subject: Find the path of a shell command (shutil.which) In-Reply-To: <5fd2939c-dcdf-7b6b-3f51-2abdd8def3ad@tompassin.net> References: <5fd2939c-dcdf-7b6b-3f51-2abdd8def3ad@tompassin.net> Message-ID: Not going to do any good if it?s not on the PATH in the first place: https://docs.python.org/3/library/shutil.html shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None) Return the path to an executable which would be run if the given cmd was called. If no cmd would be called, return None. mode is a permission mask passed to os.access(), by default determining if the file exists and executable. When no path is specified, the results of os.environ() are used, returning either the ?PATH? value or a fallback of os.defpath. From: Python-list on behalf of Thomas Passin Date: Wednesday, October 12, 2022 at 5:39 PM To: python-list at python.org Subject: Re: Find the path of a shell command *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** On 10/12/2022 12:00 AM, Paulo da Silva wrote: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > > Thanks for any comments/responses. > Paulo > Python has a command that usually does the job: import shutil, os executable_path = shutil.which(exename, os.X_OK) If you know that the executable you want is on some non-standard path, you can or them together: executable_path = shutil.which(exename, os.X_OK)\ or shutil.which(exename, os.X_OK, other_path) Presumably the shutil command uses which behind the scenes, but that doesn't matter. Now you can include this location when you run the executable from Python. If you need to run a system command from a batch file and not from Python, you will either need to have the right path in effect when the batch file is run, or manually include the full path to the file in the batch file. BTW, on Linux Mint, which is derived from Ubuntu and Debian, rm is at $ which rm /bin/rm -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!lyWawGnR8ddR5pCSS5bC09WInoHss_eleSRXxsjbIL_ndHz2TPW246oagSmaBVekZyVjzO7zKsGqN9NpLtM$ From cs at cskk.id.au Wed Oct 12 17:50:13 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 13 Oct 2022 08:50:13 +1100 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 12Oct2022 15:16, Dan Sommers <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: >rm doesn't take that long. Why are you detaching them? For big things it takes quite a while. On slow discs it can take quite a while. For directory trees with many files it can take quite a while. For remove filesystems, even a local to your LAN NAS, it can take quite a while. Certainly I've got real world modern day things right now where "quite a while" can be many minutes. I've got an `rmr` script of my own whose entire function is to rename the target to something like `.frm.blah` and then remove `.frm.blah` in the background. I use it a _lot_. Ancient anecdote. We got funky new workstations at Uni long ago. For the first time in my life "rm filename" came back to the command prompt with no perceptable delay. So fast that I first wondered if it had worked at all. Previously we'd been using shared minicomputers (PDPs, Vaxen). Cheers, Cameron Simpson From eryksun at gmail.com Wed Oct 12 17:52:02 2022 From: eryksun at gmail.com (Eryk Sun) Date: Wed, 12 Oct 2022 16:52:02 -0500 Subject: Fail 3.10.8 version installation on Windows 11 21H2 In-Reply-To: <94974f11-16dd-deb6-2e2c-8a777354bb40@devoteam.com> References: <94974f11-16dd-deb6-2e2c-8a777354bb40@devoteam.com> Message-ID: On 10/12/22, Kirill Ratkin via Python-list wrote: > > Do anyone face issue like in log below? > > I got last installer (3.10.8) and try to install it 'for all users' with > downloading precompiled (pdb) files. There was a permission problem on the Python website that prevented downloading the 3.8.10 debug binaries and symbol files. It's fixed now. https://github.com/python/cpython/issues/98193 From jon+usenet at unequivocal.eu Wed Oct 12 17:38:27 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 12 Oct 2022 21:38:27 -0000 (UTC) Subject: Find the path of a shell command References: Message-ID: On 2022-10-12, Jon Ribbens wrote: > On 2022-10-12, Paulo da Silva wrote: >> ?s 19:14 de 12/10/22, Jon Ribbens escreveu: >>> On 2022-10-12, Paulo da Silva wrote: >>>> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>>>> Hi! >>>>> >>>>> The simple question: How do I find the full path of a shell command >>>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>>> "type rm" in command line? >>>>> >>>>> The reason: >>>>> I have python program that launches a detached rm. It works pretty well >>>>> until it is invoked by cron! I suspect that for cron we need to specify >>>>> the full path. >>>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>>> What about other commands? >>>>> >>>> Thank you all who have responded so far. >>>> I think that the the suggestion of searching the PATH env seems the best. >>>> Another thing that I thought of is that of the 'which', but, to avoid >>>> the mentioned recurrent problem of not knowing where 'which' is I would >>>> use 'type' instead. 'type' is a bash (sh?) command. >>> >>> If you're using subprocess.run / subprocess.Popen then the computer is >>> *already* searching PATH for you. >> Yes, and it works out of cron. >>> Your problem must be that your cron >>> job is being run without PATH being set, perhaps you just need to edit >>> your crontab to set PATH to something sensible. >> I could do that, but I am using /etc/cron.* for convenience. >> >>> Or just hard-code your >>> program to run '/bin/rm' explicitly, which should always work (unless >>> you're on Windows, of course!) >> It can also be in /bin, at least. > > I assume you mean /usr/bin. But it doesn't matter. As already > discussed, even if 'rm' is in /usr/bin, it will be in /bin as well > (or /usr/bin and /bin will be symlinks to the same place). > >> A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer >> searching thru PATH env. It only needs to do that once. > > I cannot think of any situation in which that will help you. But if for > some reason you really want to do that, you can use the shutil.which() > function from the standard library: > > >>> import shutil > >>> shutil.which('rm') > '/usr/bin/rm' Actually if I'm mentioning shutil I should probably mention shutil.rmtree() as well, which does the same as 'rm -r', without needing to find or run any other executables. From eryksun at gmail.com Wed Oct 12 18:14:45 2022 From: eryksun at gmail.com (Eryk Sun) Date: Wed, 12 Oct 2022 17:14:45 -0500 Subject: Find the path of a shell command (shutil.which) In-Reply-To: References: <5fd2939c-dcdf-7b6b-3f51-2abdd8def3ad@tompassin.net> Message-ID: On 10/12/22, Weatherby,Gerard wrote: > > When no path is specified, the results of > os.environ() are used, > returning either the ?PATH? value or a fallback of > os.defpath. The documentation is out of sync with what the code actually does. os.defpath is hard coded in posixpath and ntpath, but shutil.which() actually prefers to query the system's default path to use via os.confstr(), if it's supported: if path is None: path = os.environ.get("PATH", None) if path is None: try: path = os.confstr("CS_PATH") except (AttributeError, ValueError): # os.confstr() or CS_PATH is not available path = os.defpath As documented by POSIX, the CS_PATH string "can be used as a value of the PATH environment variable that accesses all of the standard utilities of POSIX.1-2017, that are provided in a manner accessible via the exec family of functions". https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html From cs at cskk.id.au Wed Oct 12 18:47:01 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 13 Oct 2022 09:47:01 +1100 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 13Oct2022 08:50, Cameron Simpson wrote: >On 12Oct2022 15:16, Dan Sommers <2QdxY4RzWzUUiLuE at potatochowder.com> wrote: >>rm doesn't take that long. Why are you detaching them? > >[...] >For remove filesystems, even a local to your LAN NAS, it can take quite >a while. Of course I meant "remote" here, not "remove". Cheers, Cameron Simpson From cs at cskk.id.au Wed Oct 12 18:50:26 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 13 Oct 2022 09:50:26 +1100 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 12Oct2022 20:54, Jon Ribbens wrote: >On 2022-10-12, Jon Ribbens wrote: >> On 2022-10-12, Joe Pfeiffer wrote: >>> Jon Ribbens writes: >>>> on Amazon Linux: >>>> >>>> $ which rm >>>> /usr/bin/rm >>>> $ sudo which rm >>>> /bin/rm >>> >>> Have some major Linux distributions not done usrmerge yet? For any that >>> have, /bin is a symbolic link to /usr/bin The above example may just be a different ordering in $PATH. >> I have immediate access to CentOS 7, Ubuntu 20, and Amazon Linux 2, >> and none of those have done that. > >Sorry, in fact they have done that - I misread your comment as being >that they had symlinked the executables not the directories. This seems >quite an unwise move to me but presumably they've thought it through. I think that modern discs are so large these days that the scenario of having a small critical /bin with a larger less critical /usr/bin on another partition are behind us except in very niche circumstances. Cheers, Cameron Simpson From hjp-python at hjp.at Wed Oct 12 19:40:29 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 01:40:29 +0200 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <20221012234029.cdgswqyejmfzxkv7@hjp.at> On 2022-10-12 21:51:39 +0100, Paulo da Silva wrote: > ?s 19:14 de 12/10/22, Jon Ribbens escreveu: > > If you're using subprocess.run / subprocess.Popen then the computer is > > *already* searching PATH for you. > Yes, and it works out of cron. > > Your problem must be that your cron > > job is being run without PATH being set, perhaps you just need to edit > > your crontab to set PATH to something sensible. The PATH in cron includes the directories with standard commands like "rm" by default. If a cron job doesn't find rm, either * rm isn't where it is supposed to be, or * PATH has been changed. > I could do that, but I am using /etc/cron.* for convenience. That may be a clue. Does any of the /etc/cron.* files set PATH to weird value? In any case I find that when debugging such problems it is helpful to find out what the actual environment is. A simple * * * * * nobody echo $PATH >> /tmp/path.$$ should do that. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Wed Oct 12 19:54:32 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 01:54:32 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: <20221012235432.5ig5xgewnsvlmkv4@hjp.at> On 2022-10-10 10:11:10 +0000, Stefan Ram wrote: > I would not use tabs in source code as they are not > displayed in the same way everywhere. Some would argue that this is a feature. Different people prefer different indentation widths. Using a single tab character for an indentation level allows everybody to view the file in their preferred layout. I have, however, found out that this requires more discipline than I and the people I work with can muster. There is always someone who accidentally converts some tabs to spaces, messing up indentation for everyone else. So I require a "indent by x spaces" rule for all projects I work on (unless the language convention have a strong preference for tabs, like in Go). In email I would always use spaces. Tabs are just too unreliable there. > Functions also come at a cost. From the Web: ^^^^^^^^^^^^ Ah yes. Your infamous aversion against useful citations strikes again. For those too lazy to use a search engine, the excerpt seems to be from https://softwarebyscience.com/very-short-functions-are-a-code-smell-an-overview-of-the-science-on-function-length/ hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Wed Oct 12 19:56:34 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 01:56:34 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> Message-ID: <20221012235634.khoecidb7ysvxi5k@hjp.at> On 2022-10-10 16:48:04 +0000, Robert Latest via Python-list wrote: > Axy wrote: > >> Also not really a justification for "shortest block first". Wanting > >> some elaboration on that. What's the value in it? > > > > Well, the value is productivity. No need to save puzzles "what this > > hanging else belongs to?" > > If you find yourself asking that question, the if-block is probably too long to > begin with. ACK. > > Code small things first and return early, same ^^^^^^^^^^^^ > > as taking a test: do easy and quick things first and boring and > > difficult ones later. > > Yes, but in that case you have a very long indented "else" block, If you return you don't have to indent the rest. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 18:59:32 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Wed, 12 Oct 2022 23:59:32 +0100 Subject: Find the path of a shell command References: Message-ID: ?s 22:38 de 12/10/22, Jon Ribbens escreveu: > On 2022-10-12, Jon Ribbens wrote: >> On 2022-10-12, Paulo da Silva wrote: >>> ?s 19:14 de 12/10/22, Jon Ribbens escreveu: >>>> On 2022-10-12, Paulo da Silva wrote: >>>>> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>>>>> Hi! >>>>>> >>>>>> The simple question: How do I find the full path of a shell command >>>>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>>>> "type rm" in command line? >>>>>> >>>>>> The reason: >>>>>> I have python program that launches a detached rm. It works pretty well >>>>>> until it is invoked by cron! I suspect that for cron we need to specify >>>>>> the full path. >>>>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>>>> What about other commands? >>>>>> >>>>> Thank you all who have responded so far. >>>>> I think that the the suggestion of searching the PATH env seems the best. >>>>> Another thing that I thought of is that of the 'which', but, to avoid >>>>> the mentioned recurrent problem of not knowing where 'which' is I would >>>>> use 'type' instead. 'type' is a bash (sh?) command. >>>> >>>> If you're using subprocess.run / subprocess.Popen then the computer is >>>> *already* searching PATH for you. >>> Yes, and it works out of cron. >>>> Your problem must be that your cron >>>> job is being run without PATH being set, perhaps you just need to edit >>>> your crontab to set PATH to something sensible. >>> I could do that, but I am using /etc/cron.* for convenience. >>> >>>> Or just hard-code your >>>> program to run '/bin/rm' explicitly, which should always work (unless >>>> you're on Windows, of course!) >>> It can also be in /bin, at least. >> >> I assume you mean /usr/bin. But it doesn't matter. As already >> discussed, even if 'rm' is in /usr/bin, it will be in /bin as well >> (or /usr/bin and /bin will be symlinks to the same place). >> >>> A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer >>> searching thru PATH env. It only needs to do that once. >> >> I cannot think of any situation in which that will help you. But if for >> some reason you really want to do that, you can use the shutil.which() >> function from the standard library: >> >> >>> import shutil >> >>> shutil.which('rm') >> '/usr/bin/rm' > > Actually if I'm mentioning shutil I should probably mention > shutil.rmtree() as well, which does the same as 'rm -r', without > needing to find or run any other executables. Except that you can't have parallel tasks, at least in an easy way. Using Popen I just launch rm's and end the script. From pfeiffer at cs.nmsu.edu Wed Oct 12 19:58:48 2022 From: pfeiffer at cs.nmsu.edu (Joe Pfeiffer) Date: Wed, 12 Oct 2022 17:58:48 -0600 Subject: Find the path of a shell command References: Message-ID: <1blepkoapz.fsf@pfeifferfamily.net> Cameron Simpson writes: > On 12Oct2022 20:54, Jon Ribbens wrote: >>On 2022-10-12, Jon Ribbens wrote: >>> On 2022-10-12, Joe Pfeiffer wrote: >>>> Jon Ribbens writes: >>>>> on Amazon Linux: >>>>> >>>>> $ which rm >>>>> /usr/bin/rm >>>>> $ sudo which rm >>>>> /bin/rm >>>> >>>> Have some major Linux distributions not done usrmerge yet? For any that >>>> have, /bin is a symbolic link to /usr/bin > > The above example may just be a different ordering in $PATH. Sure, but the point is OP can use either /bin/rm or /usr/bin/rm on the vast majority of systems and execute the same command. From hjp-python at hjp.at Wed Oct 12 20:14:23 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 02:14:23 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <20221013001423.kemxsamwqqr3yfl6@hjp.at> On 2022-10-11 09:47:52 +1100, Chris Angelico wrote: > On Tue, 11 Oct 2022 at 09:18, Cameron Simpson wrote: > > > Consider: > > if condition # no colon > code > else: > code > > To actually "restart" parsing, you have to make a guess of some sort. Right. At least one of the papers on parsing I read over the last few years (yeah, I really should try to find them again) argued that the vast majority of syntax errors is either a missing token, a superfluous token or a combination of the the two. So one strategy with good results is to heuristically try to insert or delete single tokens and check which results in the longest distance to the next error. Checking multiple possible fixes has its cost, especially since you have to do that at every error. So you can argue that it is better for productivity if you discover one error in 0.1 seconds than 10 errors in 5 seconds. > > I grew up with C and Pascal compilers which would _happily_ produce many > > complaints, usually accurate, and all manner of syntactic errors. They > > didn't stop at the first syntax error. > > Yes, because they work with a much simpler grammar. I very much doubt that. Python doesn't have a particularly complicated grammar, and C certainly doesn't have a particularly simple one. The argument that it's impossible in Python (unlike any other language), because Python is oh so special doesn't hold water. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From PythonList at DancesWithMice.info Wed Oct 12 20:22:08 2022 From: PythonList at DancesWithMice.info (dn) Date: Thu, 13 Oct 2022 13:22:08 +1300 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: Message-ID: <34900d6b-0abd-19ef-4f10-e17fc256e201@DancesWithMice.info> On 09/10/2022 23.09, Antoon Pardon wrote: > I would like a tool that tries to find as many syntax errors as possible > in a python file. I know there is the risk of false positives when a > tool tries to recover from a syntax error and proceeds but I would > prefer that over the current python strategy of quiting after the first > syntax error. I just want a tool for syntax errors. No style > enforcements. Any recommandations? -- Antoon Pardon Am not sure if have really understood problem being addressed, because it seems 'answered' - perhaps the question says more about the tool-set being utilised... As someone who used to manually check and re-check code before submitting (first punched-cards, and later edited files) source to a compiler, it took some re-education to learn what to expect from a modern/language-intelligent IDE. The topic was a major interest back in the days of batch-compilers. Plus we had other tools, eg CREF/XREF utilities which produced cross-references of identifier usage - and illustrated typos in identifiers, usage before value-assignment, etc (per request from one respondent). Using an IDE which is inspecting source-code as it is being typed (or when an existing file is opened) will suggest what might?should be typed 'next' (a mixed blessing IMHO!), and secondly highlights errors until they are noticed and dealt-with. Some, especially warnings, can be safely ignored - and yes, some are spurious and SHOULD be ignored!. PyCharm* displays a number of indicators. The least intrusive appears in the top-right corner of the editor-tab listing, eg 8 errors, 2 warnings. So, apparently not 'stopping' at first error found. Within the source-code itself, there are high-lights and under-lines (in and amongst the syntax highlighting presentation/theme) - which I suppose are easier to notice during data-entry if one is a touch-typist. Accordingly, not much of a context for multiple errors to be committed during a single coding-session, but remaining un-noticed until 'the end'. For illustration, I took a simple tutorial* routine and deliberately introduced some/many of the types of error discussed within this thread. It would have been ideal to attach a graphic but here are some lines of code, under which I have attempted to represent a highlighted character (related to the line above) with an "H", and a (red) under-lined token with a "U". So, this is a feeble-attempt to show how the source is displayed and annotated by the IDE: # mis-type the tuple-assignment by adding semi-colon # which might also confuse Python into thinking of a second instruction 17 i, j = 0;, 1 H UH # replace under-line/under-score with space: s/b expected_value 25 for expected value, fibonacci_number in \ HHHHHHHHUUUUUU UUUUUUUUUUUUUUUU # mis-type the name of the zip built-in function 26 z ip( SERIES, fibonacci_generator() ): U UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU # add an extra character within identifier, as if 'new' identifier 28 assert expected_value == fyibonacci_number UUUUUUUUUUUUUU UUUUUUUUUUUUUUUUU # these all trivial SYNTAX errors - could have tried leaving-out a keyword, but ... Assuming the problem is not noticed/handled as the text is being typed, and in addition to the coder reviewing the work, recognising problems, and dealing with them him-/her-self; the IDE offers two follow-up mechanisms: 1 a means to jump 'focus' from the site of one error to the next, whereupon a pop-up will describe the error, eg (line 28) "Unresolved reference 'expected_value'"; which illustrates one problem in-isolation. In this case, line 28 is 'at fault' despite the fact that the 'error' is a consequence of THE problem on line 25! 2 a "Problems" Tool Window can be displayed, which will list every error and warning, with pretty, colored, icons, and the same message per example above, together with the relevant line-number, (the first two entries, as-listed, are 'warnings', and the rest are described as "errors"): Need more values to unpack:17 Statement seems to have no effect:17 # so it has picked-up both of my nefarious intentions Statement expected, found Py:COMMA:17 # as above # NB the "Py:COMMA" is from tokenize (per @Chris contribution(s)) 'in' expected:25 # logical, but confused by the space Unresolved reference 'value':25 # pretty-much had no chance with so many faults in one statement! Unresolved reference 'fibonacci_number':25 # ditto Unresolved reference 'z':26 # absolutely! ':' expected:26 # evidently re-started after the "in" and did what it could with the "z" Unresolved reference 'expected_value':28 # it would be "resolved" but for the first error on line 25 Unresolved reference 'fyibonacci_number':28 # ahah! Apparently trying to use an identifier before declaring/defining # in reality, just another typo # that said, I created the issue by inserting the "y" # if I'd mistyped the entire identifier upon first-entry, # the IDE's code-completion facility would have given choices and 'saved me' NB the content displayed in the Problems Tool Window is dynamic. Accordingly, because of the way Python works, if one 'fixes' errors in line-number sequence, closing an error 'higher up' may well cause a(nother) error 'lower down' to disappear - thus reducing the number of spurious errors one is likely to encounter as a limitation of the automated code-evaluation! -- Regards, =dn From rosuav at gmail.com Wed Oct 12 20:23:40 2022 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 13 Oct 2022 11:23:40 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <20221013001423.kemxsamwqqr3yfl6@hjp.at> References: <20221013001423.kemxsamwqqr3yfl6@hjp.at> Message-ID: On Thu, 13 Oct 2022 at 11:19, Peter J. Holzer wrote: > > On 2022-10-11 09:47:52 +1100, Chris Angelico wrote: > > On Tue, 11 Oct 2022 at 09:18, Cameron Simpson wrote: > > > > > Consider: > > > > if condition # no colon > > code > > else: > > code > > > > To actually "restart" parsing, you have to make a guess of some sort. > > Right. At least one of the papers on parsing I read over the last few > years (yeah, I really should try to find them again) argued that the > vast majority of syntax errors is either a missing token, a superfluous > token or a combination of the the two. So one strategy with good results > is to heuristically try to insert or delete single tokens and check > which results in the longest distance to the next error. > > Checking multiple possible fixes has its cost, especially since you have > to do that at every error. So you can argue that it is better for > productivity if you discover one error in 0.1 seconds than 10 errors in > 5 seconds. Maybe; but what if you report 10 errors in 5 seconds, but 8 of them are spurious? You've reported two useful errors in a sea of noise. Even if it's the other way around (8 where you nailed it and correctly reported the error, 2 that are nonsense), is it actually helpful? Bear in mind that, if you can discover one syntax error in 0.1 seconds, you can do that check *the moment the user types a key* in the editor (which is more-or-less what happens with most syntax highlighting editors - some have a small delay to avoid being too noisy with error reporting, but same difference). Why report false errors when you can report errors one by one and know that they're true? > > > I grew up with C and Pascal compilers which would _happily_ produce many > > > complaints, usually accurate, and all manner of syntactic errors. They > > > didn't stop at the first syntax error. > > > > Yes, because they work with a much simpler grammar. > > I very much doubt that. Python doesn't have a particularly complicated > grammar, and C certainly doesn't have a particularly simple one. > > The argument that it's impossible in Python (unlike any other language), > because Python is oh so special doesn't hold water. > Never said it's because Python is special; there are a LOT of languages that are at least as complicated. Try giving multiple useful errors when there's a syntactic problem in SQL, for instance. But I do think that Pascal, especially, has a significantly simpler grammar than Python does. ChrisA From rosuav at gmail.com Wed Oct 12 20:29:22 2022 From: rosuav at gmail.com (Chris Angelico) Date: Thu, 13 Oct 2022 11:29:22 +1100 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <34900d6b-0abd-19ef-4f10-e17fc256e201@DancesWithMice.info> References: <34900d6b-0abd-19ef-4f10-e17fc256e201@DancesWithMice.info> Message-ID: On Thu, 13 Oct 2022 at 11:23, dn wrote: > # add an extra character within identifier, as if 'new' identifier > 28 assert expected_value == fyibonacci_number > UUUUUUUUUUUUUU UUUUUUUUUUUUUUUUU > > # these all trivial SYNTAX errors - could have tried leaving-out a > keyword, but ... Just to be clear, this last one is not actually a *syntax* error - it's a misspelled name, but contextually, that is clearly a name and nothing else. These are much easier to report multiples of, and typical syntax highlighters will do so. Your other two examples were both syntactic discrepancies though. ChrisA From hjp-python at hjp.at Wed Oct 12 20:45:22 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 02:45:22 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: References: <20221013001423.kemxsamwqqr3yfl6@hjp.at> Message-ID: <20221013004522.dx2opvegmd6v3evd@hjp.at> On 2022-10-13 11:23:40 +1100, Chris Angelico wrote: > On Thu, 13 Oct 2022 at 11:19, Peter J. Holzer wrote: > > On 2022-10-11 09:47:52 +1100, Chris Angelico wrote: > > > On Tue, 11 Oct 2022 at 09:18, Cameron Simpson wrote: > > > > > > > Consider: > > > > > > if condition # no colon > > > code > > > else: > > > code > > > > > > To actually "restart" parsing, you have to make a guess of some sort. > > > > Right. At least one of the papers on parsing I read over the last few > > years (yeah, I really should try to find them again) argued that the > > vast majority of syntax errors is either a missing token, a superfluous > > token or a combination of the the two. So one strategy with good results > > is to heuristically try to insert or delete single tokens and check > > which results in the longest distance to the next error. > > > > Checking multiple possible fixes has its cost, especially since you have > > to do that at every error. So you can argue that it is better for > > productivity if you discover one error in 0.1 seconds than 10 errors in > > 5 seconds. > > Maybe; but what if you report 10 errors in 5 seconds, but 8 of them > are spurious? You've reported two useful errors in a sea of noise. > Even if it's the other way around (8 where you nailed it and correctly > reported the error, 2 that are nonsense), is it actually helpful? Humans are pattern-matching animals. It is quite possible that seeing a bunch of related errors makes the fix more obvious than seeing them in isolation. No, I haven't done any studies on this. Yes, it is possible that all those compiler writers who spent lots of work on error recovery over the last 50 years (or longer) are delusional. > > > > I grew up with C and Pascal compilers which would _happily_ produce many > > > > complaints, usually accurate, and all manner of syntactic errors. They > > > > didn't stop at the first syntax error. > > > > > > Yes, because they work with a much simpler grammar. > > > > I very much doubt that. Python doesn't have a particularly complicated > > grammar, and C certainly doesn't have a particularly simple one. > > > > The argument that it's impossible in Python (unlike any other language), > > because Python is oh so special doesn't hold water. > > > > Never said it's because Python is special; there are a LOT of > languages that are at least as complicated. And almost all of their compilers do try to recover from errors. > But I do think that Pascal, especially, has a significantly simpler > grammar than Python does. Incidentally, Turbo Pascal was the one other example of a compiler which *didn't* try to recover. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Wed Oct 12 20:48:54 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 02:48:54 +0200 Subject: What to use for finding as many syntax errors as possible. In-Reply-To: <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> References: <008201d8dd16$718fd420$54af7c60$@gmail.com> <00b001d8dd21$01475160$03d5f420$@gmail.com> <011e01d8dd40$9896ba50$c9c42ef0$@gmail.com> <4612662b-f15e-777d-bbea-7c8906ac1de3@tompassin.net> Message-ID: <20221013004854.bkfxunyqznxp3prx@hjp.at> On 2022-10-11 14:11:56 -0400, Thomas Passin wrote: > To bring things back to the context of the original post, actual web > browsers are extremely tolerant of HTML syntax errors (including incorrect > nesting of tags) in the documents they receive. HTML5 actually specifies exactly how to recover from errors. So since every sequence of bytes results in a well-defined DOM tree you might argue (a bit tongue in cheek) that there are no syntax errors in HTML5. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From PythonList at DancesWithMice.info Wed Oct 12 22:00:20 2022 From: PythonList at DancesWithMice.info (dn) Date: Thu, 13 Oct 2022 15:00:20 +1300 Subject: for -- else: what was the motivation? In-Reply-To: <63441a88.050a0220.2fd19.ec95@mx.google.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <52599b91-d041-e239-f663-247847056c39@declassed.art> <20221009165629.5cphjckz4zzpnmgz@hjp.at> <63441a88.050a0220.2fd19.ec95@mx.google.com> Message-ID: <16aa94b9-0236-5bc4-dc3e-a15949bb844d@DancesWithMice.info> On 11/10/2022 02.13, Grant Edwards wrote: > On 2022-10-10, Chris Angelico wrote: >> On Mon, 10 Oct 2022 at 11:52, MRAB wrote: >>> >>> On 2022-10-10 00:40, dn wrote: >>>> On Sun, 9 Oct 2022 at 15:39, Axy via Python-list >>>> wrote: >>>> >>>>> "shortest block first" >>>> >>>> Have never heard this advice before. Kind-of rankled with me, as it did >>>> for others. > > I've followed that advice for several decades. I find it much easier > to read code that's organized that way -- particularly when the > difference in block sizes is large (e.g. the first block is one line, > and the second is a a hundred). Makes sense. Keep the 'cause' and 'effect' close together. In other words, making it easy to look 'up' from one of the 'suites' to see the if-statement/condition which directs that logic-branch. Contrarily, (see @Karsten, earlier) the preference to bundle the "hundred" into one or more functions, rather than present as a 'wall of text'. Added advantage: well-chosen function names(!) will remind the reader of the purposes(!) of the "hundred". Once both suites are short[ened], visibility improves (readability), and the above contention goes-away. Thus the sense of the condition becomes the most worthy consideration. -- Regards, =dn From bowman at montana.com Wed Oct 12 22:08:24 2022 From: bowman at montana.com (rbowman) Date: Wed, 12 Oct 2022 20:08:24 -0600 Subject: Find the path of a shell command In-Reply-To: References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: On 10/12/22 09:06, Chris Green wrote: > Michael F. Stemper wrote: >> On 12/10/2022 07.20, Chris Green wrote: >>> jak wrote: >>>> Il 12/10/2022 09:40, jkn ha scritto: >>>>> On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: >> >>>>>> I'm afraid you will have to look for the command in every path listed in >>>>>> the PATH environment variable. >>>>> >>>>> erm, or try 'which rm' ? >>>> >>>> You might but if you don't know where the 'rm' command is, you will have >>>> the same difficulty in using 'which' command. Do not you think? >>> From a command prompt use the bash built-in 'command' :- >>> >>> command -v rm >>> >>> ... and rm will just about always be in /usr/bin. >> >> On two different versions of Ubuntu, it's in /bin. >> > I think you'll find it's in both /bin and /usr/bin, usually /usr/bin > is earlier in the path so /usr/bin/rm is the one that will normally be > found first. > > It's only in /bin/rm in case one has a system which mounts /bin > separately and earlier in the boot sequence and rm is one of the > commands needed early on. > ls -l /bin lrwxrwxrwx 1 root root 7 Sep 23 01:41 /bin -> usr/bin From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Wed Oct 12 22:25:51 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Thu, 13 Oct 2022 03:25:51 +0100 Subject: Find the path of a shell command [POSTPONED] References: Message-ID: ?s 05:00 de 12/10/22, Paulo da Silva escreveu: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > For now I will postpone this problem. I just wrote a small script to delete a dir using rm and it works even under cron! There is another problem involved. The script, works fine except when launched by cron! Why? I'll have to look into this later when I have more time. For now I solved the problem using a complementary shell script. Thank you very much to those who responded. Paulo From cs at cskk.id.au Thu Oct 13 00:56:32 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 13 Oct 2022 15:56:32 +1100 Subject: Find the path of a shell command [POSTPONED] In-Reply-To: References: Message-ID: On 13Oct2022 03:25, Paulo da Silva wrote: >There is another problem involved. The script, works fine except when >launched by cron! Why? Record the script output: # record all output exec >/tmp/script.$$.out 2>&1 # dump the envionment env | sort # turn on execution tracing set -x ... rest of the script and have a look afterwards. Cron's environment is very minimal. This will show you what's in it. Cheers, Cameron Simpson From mats at wichmann.us Thu Oct 13 10:27:23 2022 From: mats at wichmann.us (Mats Wichmann) Date: Thu, 13 Oct 2022 08:27:23 -0600 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <597fbe02-9e37-3e1c-873e-1e04fac62a0c@wichmann.us> On 10/12/22 14:51, Paulo da Silva wrote: > ?s 19:14 de 12/10/22, Jon Ribbens escreveu: >> On 2022-10-12, Paulo da Silva >> wrote: >>> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>>> Hi! >>>> >>>> The simple question: How do I find the full path of a shell command >>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>> "type rm" in command line? >>>> >>>> The reason: >>>> I have python program that launches a detached rm. It works pretty well >>>> until it is invoked by cron! I suspect that for cron we need to specify >>>> the full path. >>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>> What about other commands? >>>> >>> Thank you all who have responded so far. >>> I think that the the suggestion of searching the PATH env seems the >>> best. >>> Another thing that I thought of is that of the 'which', but, to avoid >>> the mentioned recurrent problem of not knowing where 'which' is I would >>> use 'type' instead. 'type' is a bash (sh?) command. >> >> If you're using subprocess.run / subprocess.Popen then the computer is >> *already* searching PATH for you. > Yes, and it works out of cron. >> Your problem must be that your cron >> job is being run without PATH being set, perhaps you just need to edit >> your crontab to set PATH to something sensible. > I could do that, but I am using /etc/cron.* for convenience. > >> Or just hard-code your >> program to run '/bin/rm' explicitly, which should always work (unless >> you're on Windows, of course!) > It can also be in /bin, at least. > A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer > searching thru PATH env. It only needs to do that once. I've read quite a bit of this thread without completely understanding the actual problem. Crontabs have always been good at exposing the problem of "is my program expecting something to be set up which isn't guaranteed?" - usually environment variables, of which PATH is one. "But it worked from my login shell....". Python's standard library has a tool for you: shutil.which = which(cmd, mode=1, path=None) Given a command, mode, and a PATH string, return the path which conforms to the given mode on the PATH, or None if there is no such file. `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result of os.environ.get("PATH"), or can be overridden with a custom search path. Since cron usually runs in a minimal environment, you should be able to use this to supply a decent value for PATH, look up the command you need, and then use that path to launch the command - or fail in some sort of graceful way if not found, so you can hear about it and make corrections. From sarah.wallace00 at gmail.com Thu Oct 13 08:44:04 2022 From: sarah.wallace00 at gmail.com (Sarah Wallace) Date: Thu, 13 Oct 2022 07:44:04 -0500 Subject: Fwd: Can you help me with this Python question? In-Reply-To: References: Message-ID: For a python class I am taking.. In this challenge, you'll be working with a DataFrame that contains data about artworks, and it contains many missing values. Your task is to create a variable called na_sum that contains the total number of missing values in the DataFrame. When that's completed, print out your answer! Hint: The code given below will give you the number of missing (NaN) values for the *Name* column in the DataFrame. How would you edit the code to get the missing values for every column in the DataFrame? Extra hint: You'll be returning a single number which is the final sum() of everything. df['Name'].isnull().sum() -- Thanks! *Sarah Wallace* sarah.wallace00 at gmail.com -- Thanks! *Sarah Wallace* sarah.wallace00 at gmail.com 214.300.1064 From * at eli.users.panix.com Thu Oct 13 00:46:05 2022 From: * at eli.users.panix.com (Eli the Bearded) Date: Thu, 13 Oct 2022 04:46:05 -0000 (UTC) Subject: Find the path of a shell command References: <0a8174ee-444a-474c-a0cf-72ef320041fan@googlegroups.com> Message-ID: In comp.lang.python, jkn wrote: > On Wednesday, October 12, 2022 at 6:12:23 AM UTC+1, jak wrote: >> I'm afraid you will have to look for the command in every path listed in >> the PATH environment variable. > erm, or try 'which rm' ? It is so hilarious seeing the responses to this thread. Hint: what do you think the `which` program does? $ touch /var/tmp/rm $ chmod 755 /var/tmp/rm $ env -i PATH=/etc:/usr:/lib:/var/tmp:/tmp /usr/bin/which rm /var/tmp/rm $ mv /var/tmp/rm /tmp/ $ env -i PATH=/etc:/usr:/lib:/var/tmp:/tmp /usr/bin/which rm /tmp/rm $ Elijah ------ /usr/bin/busybox rm /tmp/rm From jon+usenet at unequivocal.eu Thu Oct 13 07:26:14 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Thu, 13 Oct 2022 11:26:14 -0000 (UTC) Subject: Find the path of a shell command References: Message-ID: On 2022-10-12, Paulo da Silva wrote: > ?s 22:38 de 12/10/22, Jon Ribbens escreveu: >> On 2022-10-12, Jon Ribbens wrote: >>> On 2022-10-12, Paulo da Silva wrote: >>>> ?s 19:14 de 12/10/22, Jon Ribbens escreveu: >>>>> On 2022-10-12, Paulo da Silva wrote: >>>>>> ?s 05:00 de 12/10/22, Paulo da Silva escreveu: >>>>>>> Hi! >>>>>>> >>>>>>> The simple question: How do I find the full path of a shell command >>>>>>> (linux), i.e. how do I obtain the corresponding of, for example, >>>>>>> "type rm" in command line? >>>>>>> >>>>>>> The reason: >>>>>>> I have python program that launches a detached rm. It works pretty well >>>>>>> until it is invoked by cron! I suspect that for cron we need to specify >>>>>>> the full path. >>>>>>> Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? >>>>>>> What about other commands? >>>>>>> >>>>>> Thank you all who have responded so far. >>>>>> I think that the the suggestion of searching the PATH env seems the best. >>>>>> Another thing that I thought of is that of the 'which', but, to avoid >>>>>> the mentioned recurrent problem of not knowing where 'which' is I would >>>>>> use 'type' instead. 'type' is a bash (sh?) command. >>>>> >>>>> If you're using subprocess.run / subprocess.Popen then the computer is >>>>> *already* searching PATH for you. >>>> Yes, and it works out of cron. >>>>> Your problem must be that your cron >>>>> job is being run without PATH being set, perhaps you just need to edit >>>>> your crontab to set PATH to something sensible. >>>> I could do that, but I am using /etc/cron.* for convenience. >>>> >>>>> Or just hard-code your >>>>> program to run '/bin/rm' explicitly, which should always work (unless >>>>> you're on Windows, of course!) >>>> It can also be in /bin, at least. >>> >>> I assume you mean /usr/bin. But it doesn't matter. As already >>> discussed, even if 'rm' is in /usr/bin, it will be in /bin as well >>> (or /usr/bin and /bin will be symlinks to the same place). >>> >>>> A short idea is to just check /bin/rm and /usr/bin/rm, but I prefer >>>> searching thru PATH env. It only needs to do that once. >>> >>> I cannot think of any situation in which that will help you. But if for >>> some reason you really want to do that, you can use the shutil.which() >>> function from the standard library: >>> >>> >>> import shutil >>> >>> shutil.which('rm') >>> '/usr/bin/rm' >> >> Actually if I'm mentioning shutil I should probably mention >> shutil.rmtree() as well, which does the same as 'rm -r', without >> needing to find or run any other executables. > Except that you can't have parallel tasks, at least in an easy way. > Using Popen I just launch rm's and end the script. [threading.Thread(target=shutil.rmtree, args=(item,)).start() for item in items_to_delete] From cl at isbd.net Thu Oct 13 08:47:07 2022 From: cl at isbd.net (Chris Green) Date: Thu, 13 Oct 2022 13:47:07 +0100 Subject: What might suddenly provoke this poplib error? Message-ID: I have a short python3 program that collects E-Mails from a 'catchall' mailbox, sends the few that might be interesting to me and dumps the rest. It has suddenly (after working for some years) started throwing the following:- Traceback (most recent call last): File "/home/chris/.mutt/bin/getCatchall.py", line 83, in pop3.pass_('brzmilla') File "/usr/lib/python3.10/poplib.py", line 218, in pass_ return self._shortcmd('PASS %s' % pswd) File "/usr/lib/python3.10/poplib.py", line 181, in _shortcmd return self._getresp() File "/usr/lib/python3.10/poplib.py", line 157, in _getresp raise error_proto(resp) poplib.error_proto: b'-ERR internal server error' The section of code throwing the error is as follows:- # # # Connect to the POP3 server, get message count, exit if no messages # for t in range(10): # retry 10 times try: pop3 = poplib.POP3_SSL('mail3.gridhost.co.uk',timeout=300) break except TimeoutError: if t == 9: log.err("Timed out 10 times, giving up") exit(1) else: log.warn("Timed out, try " + str(t)) pop3.user('catchall at isbd.net') pop3.pass_('brzmilla') numMessages = len(pop3.list()[1]) if (numMessages == 0): break It seems to be saying that the POP3 server has a problem, if so there's not much I can do about it as it's my hosting provider's mail server. Is it really saying the server has a problem? -- Chris Green ? From cl at isbd.net Thu Oct 13 08:53:34 2022 From: cl at isbd.net (Chris Green) Date: Thu, 13 Oct 2022 13:53:34 +0100 Subject: What might suddenly provoke this poplib error? References: Message-ID: A further little bit of information, I tried running getCatchall.py from the command prompt and there was a long wait before it output the same error message. I.e. it looks rather as if the server is not responding to requests. (A 'long wait' is a minute or two) -- Chris Green ? From python at mrabarnett.plus.com Thu Oct 13 13:35:11 2022 From: python at mrabarnett.plus.com (MRAB) Date: Thu, 13 Oct 2022 18:35:11 +0100 Subject: What might suddenly provoke this poplib error? In-Reply-To: References: Message-ID: <4a99d25f-b795-d727-09d0-e8086e3be11f@mrabarnett.plus.com> On 2022-10-13 13:47, Chris Green wrote: > I have a short python3 program that collects E-Mails from a 'catchall' > mailbox, sends the few that might be interesting to me and dumps the > rest. > > It has suddenly (after working for some years) started throwing the > following:- > > Traceback (most recent call last): > File "/home/chris/.mutt/bin/getCatchall.py", line 83, in > pop3.pass_('brzmilla') > File "/usr/lib/python3.10/poplib.py", line 218, in pass_ > return self._shortcmd('PASS %s' % pswd) > File "/usr/lib/python3.10/poplib.py", line 181, in _shortcmd > return self._getresp() > File "/usr/lib/python3.10/poplib.py", line 157, in _getresp > raise error_proto(resp) > poplib.error_proto: b'-ERR internal server error' > > > The section of code throwing the error is as follows:- > > # > # > # Connect to the POP3 server, get message count, exit if no messages > # > for t in range(10): # retry 10 times > try: > pop3 = poplib.POP3_SSL('mail3.gridhost.co.uk',timeout=300) > break > except TimeoutError: > if t == 9: > log.err("Timed out 10 times, giving up") > exit(1) > else: > log.warn("Timed out, try " + str(t)) > > pop3.user('catchall at isbd.net') > pop3.pass_('brzmilla') > numMessages = len(pop3.list()[1]) > if (numMessages == 0): > break > > > It seems to be saying that the POP3 server has a problem, if so there's not > much I can do about it as it's my hosting provider's mail server. Is it > really saying the server has a problem? > As you've already ascertained that it's a server error, I'd just like to suggest that you add a sleep before retrying. If it has timed out after 5 minutes, I doubt there's much point in retrying immediately. From hjp-python at hjp.at Thu Oct 13 13:43:16 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Thu, 13 Oct 2022 19:43:16 +0200 Subject: What might suddenly provoke this poplib error? In-Reply-To: References: Message-ID: <20221013174316.oep3ajplomj6jexq@hjp.at> On 2022-10-13 13:47:07 +0100, Chris Green wrote: > I have a short python3 program that collects E-Mails from a 'catchall' > mailbox, sends the few that might be interesting to me and dumps the > rest. > > It has suddenly (after working for some years) started throwing the > following:- [...] > poplib.error_proto: b'-ERR internal server error' [...] > It seems to be saying that the POP3 server has a problem, Yes. "-ERR" is the normal start of a POP error reply, so the message "-ERR internal server error" was sent by the POP server. > if so there's not much I can do about it as it's my hosting provider's > mail server. You can call you hosting provider and ask them to fix the problem. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From axy at declassed.art Thu Oct 13 13:47:32 2022 From: axy at declassed.art (Axy) Date: Thu, 13 Oct 2022 18:47:32 +0100 Subject: Fwd: Can you help me with this Python question? In-Reply-To: References: Message-ID: <81adae8f-92c1-4a35-581f-fc9f4e72b94d@declassed.art> Well, although I never used pandas and never will, if that's about artworks, that's mine. Obviously, you need to iterate columns and sum values returned by the snippet you provided. A quick search tells us to use colums property. So, it might look like this: na_sum = sum(df[name].isnull().sum() for name in df.columns) Axy On 13/10/2022 13:44, Sarah Wallace wrote: > For a python class I am taking.. > > In this challenge, you'll be working with a DataFrame that contains data > about artworks, and it contains many missing values. > > Your task is to create a variable called na_sum that contains the total > number of missing values in the DataFrame. When that's completed, print out > your answer! > > Hint: The code given below will give you the number of missing (NaN) values > for the *Name* column in the DataFrame. How would you edit the code to get > the missing values for every column in the DataFrame? > Extra hint: You'll be returning a single number which is the final sum() of > everything. > > df['Name'].isnull().sum() > From PythonList at DancesWithMice.info Thu Oct 13 18:31:56 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 14 Oct 2022 11:31:56 +1300 Subject: What might suddenly provoke this poplib error? In-Reply-To: References: Message-ID: <07ebefc6-517b-3a3f-48b1-2c37be173b1d@DancesWithMice.info> On 14/10/2022 01.47, Chris Green wrote: > I have a short python3 program that collects E-Mails from a 'catchall' > mailbox, sends the few that might be interesting to me and dumps the > rest. > > It has suddenly (after working for some years) started throwing the > following:- > > Traceback (most recent call last): > File "/home/chris/.mutt/bin/getCatchall.py", line 83, in > pop3.pass_('brzmilla') > File "/usr/lib/python3.10/poplib.py", line 218, in pass_ > return self._shortcmd('PASS %s' % pswd) > File "/usr/lib/python3.10/poplib.py", line 181, in _shortcmd > return self._getresp() > File "/usr/lib/python3.10/poplib.py", line 157, in _getresp > raise error_proto(resp) > poplib.error_proto: b'-ERR internal server error' > > > The section of code throwing the error is as follows:- > > # > # > # Connect to the POP3 server, get message count, exit if no messages > # > for t in range(10): # retry 10 times > try: > pop3 = poplib.POP3_SSL('mail3.gridhost.co.uk',timeout=300) > break > except TimeoutError: > if t == 9: > log.err("Timed out 10 times, giving up") > exit(1) > else: > log.warn("Timed out, try " + str(t)) > > pop3.user('catchall at isbd.net') > pop3.pass_('brzmilla') > numMessages = len(pop3.list()[1]) > if (numMessages == 0): > break > > > It seems to be saying that the POP3 server has a problem, if so there's not > much I can do about it as it's my hosting provider's mail server. Is it > really saying the server has a problem? There's a range of possibilities here. The first question to ask (as you probably have) is "what has changed?" - has the Python/PSL on this computer been updated*, has the computer's SSL/TLS library been updated, etc. Then there are possible changes at 'the other end' - per previous responses. * IIRC the last changes to email lib were circa 3.5, but poplib's doc page shows more recent updates - including to timeouts in v3.9 (YMMV). There are changes afoot in the TLS arena. Older algorithms being dumped, and newer, stronger, harder, faster, better mechanisms (with racing stripes) being added. Not using POP3, I can't say how much impact such may have... Try using an independent checker to investigate continuity of access. From your own machine (I use "s_client -connect..." but for IMAP), thus should be able to replicate the 'error' conversation at the level of the POP3 'conversation'. Alternately, use an on-line service such as: https://www.wormly.com/test-pop3-mail-server Disclaimer: again, not using POP3, I have never used this service, it 'popped-up' whilst searching on DuckDuckGo. Many general-purpose service/server-providers seem rather heavy-handed when it comes to email security, often as a result of some knee-jerk response to a 'live-issue' - ultimately caused by them not having competent email-specialists on-staff. Accordingly, they may have 'changed policy' and 'forgotten' to let mere-clients know. (although, if your standard email access continues unabated, this seems less-likely) That said, it never hurts to ask/be in friendly-contact... PS is that really your password? If so, ... -- Regards, =dn From cl at isbd.net Thu Oct 13 19:02:27 2022 From: cl at isbd.net (Chris Green) Date: Fri, 14 Oct 2022 00:02:27 +0100 Subject: What might suddenly provoke this poplib error? References: <4a99d25f-b795-d727-09d0-e8086e3be11f@mrabarnett.plus.com> Message-ID: <31im1j-j9b21.ln1@esprimo.zbmc.eu> MRAB wrote: [snip boring code] > > > > It seems to be saying that the POP3 server has a problem, if so there's not > > much I can do about it as it's my hosting provider's mail server. Is it > > really saying the server has a problem? > > > As you've already ascertained that it's a server error, I'd just like to > suggest that you add a sleep before retrying. If it has timed out after > 5 minutes, I doubt there's much point in retrying immediately. I guess I could do that but this has only happened once in quite a few years so I'm not sure if I;ll bother! :-) The program is only run half-hourly by cron. -- Chris Green ? From cl at isbd.net Thu Oct 13 19:00:02 2022 From: cl at isbd.net (Chris Green) Date: Fri, 14 Oct 2022 00:00:02 +0100 Subject: What might suddenly provoke this poplib error? References: <20221013174316.oep3ajplomj6jexq@hjp.at> Message-ID: Peter J. Holzer wrote: > [-- text/plain, encoding quoted-printable, charset: us-ascii, 28 lines --] > > On 2022-10-13 13:47:07 +0100, Chris Green wrote: > > I have a short python3 program that collects E-Mails from a 'catchall' > > mailbox, sends the few that might be interesting to me and dumps the > > rest. > > > > It has suddenly (after working for some years) started throwing the > > following:- > [...] > > poplib.error_proto: b'-ERR internal server error' > [...] > > It seems to be saying that the POP3 server has a problem, > > Yes. "-ERR" is the normal start of a POP error reply, so the message > "-ERR internal server error" was sent by the POP server. > > > if so there's not much I can do about it as it's my hosting provider's > > mail server. > > You can call you hosting provider and ask them to fix the problem. > After a couple of hours someone obviously fixed something and the error has stopped now. Thanks everyone. -- Chris Green ? From torriem at gmail.com Thu Oct 13 19:24:06 2022 From: torriem at gmail.com (Michael Torrie) Date: Thu, 13 Oct 2022 17:24:06 -0600 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On 10/11/22 22:00, Paulo da Silva wrote: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? There are certain standards that suggest where to look. For example, there's the Linux Filesystem Hiearchy Standard 3.0: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s04.html In short, you want to hard code /bin for a command like rm. And yes it will always be in /bin on any standard Linux OS. Despite modern distros making /bin and /usr/bin the same directory, if the target OS is anywhere close to the standard, you can always find the basic commands in /bin. I would not hard code any script to use /usr/bin for any basic commands and I would not use anything other than /bin/sh or /bin/bash as the shell script shebang if you want any sort of portability. From hjp-python at hjp.at Fri Oct 14 04:39:35 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Fri, 14 Oct 2022 10:39:35 +0200 Subject: What might suddenly provoke this poplib error? In-Reply-To: <07ebefc6-517b-3a3f-48b1-2c37be173b1d@DancesWithMice.info> References: <07ebefc6-517b-3a3f-48b1-2c37be173b1d@DancesWithMice.info> Message-ID: <20221014083935.zi2zwkglbwfu4mgf@hjp.at> [The OP has stated that the problem has been fixed. The following are generic comments about troubleshooting.] On 2022-10-14 11:31:56 +1300, dn wrote: > On 14/10/2022 01.47, Chris Green wrote: > > File "/usr/lib/python3.10/poplib.py", line 157, in _getresp > > raise error_proto(resp) > > poplib.error_proto: b'-ERR internal server error' ... > > It seems to be saying that the POP3 server has a problem, if so > > there's not much I can do about it as it's my hosting provider's > > mail server. Is it really saying the server has a problem? > > > There's a range of possibilities here. The first question to ask (as > you probably have) is "what has changed?" - has the Python/PSL on this > computer been updated*, has the computer's SSL/TLS library been > updated, etc. Then there are possible changes at 'the other end' - per > previous responses. I think this should be the second question. The first quesion is: What are the actual symptoms? In this case we have a relatively clear error message which was obviously[2] sent by the server. So anything else must[1] be consistent with this error message (and the fact that we were able to get this error message in the first place). So it can't[1] be TLS, because if you can't establish a connection, the server can't send an error message. The message also says "internal server error", and this is not something a client should be able to provoke. So it's unlikely to be anything on the client side. What's left is that there was a change or operational error on the server side, so further analysis must be conducted there. hp [1] Take absolute assertions like this with a grain of salt. There are always misleading error messages, weird edge cases, etc. But consider those only after ruling out everything else. [2] What may be obvious to one person is of course not necessarily obvious to another. -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From drsalists at gmail.com Fri Oct 14 10:40:14 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Fri, 14 Oct 2022 07:40:14 -0700 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: On Wed, Oct 12, 2022 at 11:13 AM Paulo da Silva < p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > Hi! > > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? > I like to test my cronjobs with something like: env - /usr/local/bin/my-cronjob This will empty out the environment, and force you to set $PATH yourself. Alternatively, you can "ps axfwwe" (on Linux) to see environment variables, and check what the environment of cron (or similar) is. It is this environment (mostly) that cronjobs will inherit. From hjp-python at hjp.at Fri Oct 14 12:19:32 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Fri, 14 Oct 2022 18:19:32 +0200 Subject: Find the path of a shell command In-Reply-To: References: Message-ID: <20221014161932.nhwiczy67orgienv@hjp.at> On 2022-10-14 07:40:14 -0700, Dan Stromberg wrote: > Alternatively, you can "ps axfwwe" (on Linux) to see environment > variables, and check what the environment of cron (or similar) is. It > is this environment (mostly) that cronjobs will inherit. The simplest (and IMHO also most reliable) way to find out the environment a cronjob has is to write a cronjob which just dumps the environment. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From sjeik_appie at hotmail.com Fri Oct 14 13:57:45 2022 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Fri, 14 Oct 2022 19:57:45 +0200 Subject: Find the path of a shell command In-Reply-To: <20221014161932.nhwiczy67orgienv@hjp.at> Message-ID: On Oct 14, 2022 18:19, "Peter J. Holzer" wrote: On 2022-10-14 07:40:14 -0700, Dan Stromberg wrote: > Alternatively, you can "ps axfwwe" (on Linux) to see environment > variables, and check what the environment of cron (or similar) is.? It > is this environment (mostly) that cronjobs will inherit. The simplest (and IMHO also most reliable) way to find out the environment a cronjob has is to write a cronjob which just dumps the environment. ?? ===== Lately I've been using systemd timers instead of cronjobs. They are easier to debug (journalctl) but require a bit more work to write. Systemd is available on Fedora & friends and Debian based systems, maybe more. It has no builtin MAILTO. I use an OnFailure stanza to send a Slack message with curl instead. https://www.freedesktop.org/software/systemd/man/systemd.timer.html https://unix.stackexchange.com/questions/278564/cron-vs-systemd-timers From gweatherby at uchc.edu Fri Oct 14 15:17:29 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Fri, 14 Oct 2022 19:17:29 +0000 Subject: systemd Re: Find the path of a shell command In-Reply-To: References: <20221014161932.nhwiczy67orgienv@hjp.at> Message-ID: Only the first one or two require more work. The rest are your copy-pastes from the last time you did one. Typically I only have to changed descriptions, the executable in the *service and the timing in the *timer. They?re lot more readable and flexible than the cronjobs. From: Python-list on behalf of Albert-Jan Roskam Date: Friday, October 14, 2022 at 1:59 PM To: Peter J. Holzer Cc: python-list at python.org ===== Lately I've been using systemd timers instead of cronjobs. They are easier to debug (journalctl) but require a bit more work to write. Systemd is available on Fedora & friends and Debian based systems, maybe more. It has no builtin MAILTO. I use an OnFailure stanza to send a Slack message with curl instead. https://urldefense.com/v3/__https://www.freedesktop.org/software/systemd/man/systemd.timer.html__;!!Cn_UX_p3!l6ZRc2Ur6rwspaC1V71wsENqmq5RNIR3lU2suC1LJLzYp097e-r2NwNBD3a_RhjuUkrSmfq3emmUsY-1m0PxT2TM$ https://urldefense.com/v3/__https://unix.stackexchange.com/questions/278564/cron-vs-systemd-timers__;!!Cn_UX_p3!l6ZRc2Ur6rwspaC1V71wsENqmq5RNIR3lU2suC1LJLzYp097e-r2NwNBD3a_RhjuUkrSmfq3emmUsY-1m6sDQHR0$ -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!l6ZRc2Ur6rwspaC1V71wsENqmq5RNIR3lU2suC1LJLzYp097e-r2NwNBD3a_RhjuUkrSmfq3emmUsY-1m3Q-bOmf$ From rob.cliffe at btinternet.com Wed Oct 12 18:19:39 2022 From: rob.cliffe at btinternet.com (Rob Cliffe) Date: Wed, 12 Oct 2022 23:19:39 +0100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> Message-ID: <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> I too have occasionally used for ... else.? It does have its uses. But oh, how I wish it had been called something else more meaningful, whether 'nobreak' or whatever.? It used to really confuse me.? Now I've learned to mentally replace "else" by "if nobreak", it confuses me a bit less. Rob Cliffe On 12/10/2022 22:11, Weatherby,Gerard wrote: > As did I. > > tree = ET.parse(lfile) > for child in tree.getroot(): > if child.tag == 'server': > break > else: > raise ValueError(f"server tag not found in {lfile}") > > I think there are other places I could be using it, but honestly I tend to forget it?s available. > > From: Python-list on behalf of Stefan Ram > Date: Wednesday, October 12, 2022 at 2:22 PM > To: python-list at python.org > Subject: Re: for -- else: what was the motivation? > *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > > Axy writes: >> So, seriously, why they needed else if the following pieces produce same >> result? Does anyone know or remember their motivation? > Just wrote code wherein I used "else"! This: > > import locale > for name in( 'de', 'de_DE', 'deu_deu', 'deu', 'German', 'Deutsch' ): > try: locale.setlocale( locale.LC_ALL, name ); break > except locale.Error: pass > else: print( "Programm kann deutsche Schreibweise nicht einrichten." ) > > . > > > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!iyDac-XjNlj78G0XwNzZ-FEHyuCZIy33n3cI9MUDM_FnEdR04mSQ5Ln0OA1ETUNloyH24iY9meNHVdixLgWRYL8$ From grant.b.edwards at gmail.com Sat Oct 15 11:16:04 2022 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Sat, 15 Oct 2022 08:16:04 -0700 (PDT) Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> =?utf-8?q?=3CSA1PR14MB5855ACA?= =?utf-8?q?09183821BF6756E0DB9229=40SA1PR14MB5855=2Enamprd14=2Eprod=2Eoutloo?= =?utf-8?q?k=2Ecom=3E?= <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> Message-ID: <634aceb4.050a0220.118a5.2bac@mx.google.com> On 2022-10-12, Rob Cliffe via Python-list wrote: > I too have occasionally used for ... else.? It does have its uses. But > oh, how I wish it had been called something else more meaningful, > whether 'nobreak' or whatever. I use it a few times year. I have to look it up in the documentation every single time I do, and I always add a comment in the "else" clause stating whether the looped completed "normally" or not. -- Grant From avi.e.gross at gmail.com Sat Oct 15 18:50:14 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sat, 15 Oct 2022 18:50:14 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> Message-ID: <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> This has been discussed so often precisely because I swear NO CHOICE of keyword would satisfy everybody! Most languages start with designated keywords and some reserve a few for later use. But then things can get frozen in place to avoid breaking existing programs or break older compilers/interpreters. Some languages use techniques to extend themselves more harmlessly such as creating a singleton object that has content that can be regular data as in math.pi, or functions/methods or new ides like "Symbols" that allow all kinds of extensions to the language in a fairly harmless way as no older program would likely have used features that did not exist. That might not easily solve this problem. But I wonder if reserving some kind of prefix might help, so anything like extension.0nNoBreak could be added to a loop as a final clause and be treated as a non-key keyword of sorts. -----Original Message----- From: Python-list On Behalf Of Rob Cliffe via Python-list Sent: Wednesday, October 12, 2022 6:20 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? I too have occasionally used for ... else. It does have its uses. But oh, how I wish it had been called something else more meaningful, whether 'nobreak' or whatever. It used to really confuse me. Now I've learned to mentally replace "else" by "if nobreak", it confuses me a bit less. Rob Cliffe On 12/10/2022 22:11, Weatherby,Gerard wrote: > As did I. > > tree = ET.parse(lfile) > for child in tree.getroot(): > if child.tag == 'server': > break > else: > raise ValueError(f"server tag not found in {lfile}") > > I think there are other places I could be using it, but honestly I tend to forget it?s available. > > From: Python-list > on behalf of Stefan Ram > Date: Wednesday, October 12, 2022 at 2:22 PM > To: python-list at python.org > Subject: Re: for -- else: what was the motivation? > *** Attention: This is an external email. Use caution responding, > opening attachments or clicking on links. *** > > Axy writes: >> So, seriously, why they needed else if the following pieces produce >> same result? Does anyone know or remember their motivation? > Just wrote code wherein I used "else"! This: > > import locale > for name in( 'de', 'de_DE', 'deu_deu', 'deu', 'German', 'Deutsch' ): > try: locale.setlocale( locale.LC_ALL, name ); break > except locale.Error: pass > else: print( "Programm kann deutsche Schreibweise nicht einrichten." ) > > . > > > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/p > ython-list__;!!Cn_UX_p3!iyDac-XjNlj78G0XwNzZ-FEHyuCZIy33n3cI9MUDM_FnEd > R04mSQ5Ln0OA1ETUNloyH24iY9meNHVdixLgWRYL8$ _https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!iyDa > c-XjNlj78G0XwNzZ-FEHyuCZIy33n3cI9MUDM_FnEdR04mSQ5Ln0OA1ETUNloyH24iY9me > NHVdixLgWRYL8$> -- https://mail.python.org/mailman/listinfo/python-list From drsalists at gmail.com Sat Oct 15 23:49:55 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Sat, 15 Oct 2022 20:49:55 -0700 Subject: Find the path of a shell command [POSTPONED] In-Reply-To: References: Message-ID: On Wed, Oct 12, 2022 at 9:57 PM Cameron Simpson wrote: > On 13Oct2022 03:25, Paulo da Silva > wrote: > >There is another problem involved. The script, works fine except when > >launched by cron! Why? > > Record the script output: > > # record all output > exec >/tmp/script.$$.out 2>&1 > # dump the envionment > env | sort > # turn on execution tracing > set -x > ... rest of the script > > and have a look afterwards. Cron's environment is very minimal. This > will show you what's in it. > Careful. On some systems if someone restarts the cron daemon, it could pick up a larger environment than after being started on boot. From antoon.pardon at vub.be Sun Oct 16 06:17:39 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 12:17:39 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> Message-ID: <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Op 16/10/2022 om 00:50 schreef avi.e.gross at gmail.com: > This has been discussed so often precisely because I swear NO CHOICE of keyword would satisfy everybody! Most languages start with designated keywords and some reserve a few for later use. But then things can get frozen in place to avoid breaking existing programs or break older compilers/interpreters. > > Some languages use techniques to extend themselves more harmlessly such as creating a singleton object that has content that can be regular data as in math.pi, or functions/methods or new ides like "Symbols" that allow all kinds of extensions to the language in a fairly harmless way as no older program would likely have used features that did not exist. > > That might not easily solve this problem. But I wonder if reserving some kind of prefix might help, so anything like extension.0nNoBreak could be added to a loop as a final clause and be treated as a non-key keyword of sorts. My idea would be to reserve different unicode blocks for the keywords and the identifiers. e.g. We could reserve the mathematical alphanumeric block for keywords and all other letters and numbers for identifiers. Doing so would allow extenting the keywords without breaking programs that already use that combination as an identifier. Python could slowly transition in this direction by first allowing the current keywords to be in this block. Every new keyword would only be in that unicode block. If would then be possible to write python code with this convention but it wouldn't be obligatory. After some time the python developers could decide to make it obligatory. I doubt this will idea will get from the ground, but I think it would allow for a smoother transition into new concepts, as it is no longer a strugle searching for a keyword that will break as little programs as possible. -- Antoon Pardon. From rosuav at gmail.com Sun Oct 16 07:03:04 2022 From: rosuav at gmail.com (Chris Angelico) Date: Sun, 16 Oct 2022 22:03:04 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Message-ID: On Sun, 16 Oct 2022 at 21:19, Antoon Pardon wrote: > > Op 16/10/2022 om 00:50 schreef avi.e.gross at gmail.com: > > This has been discussed so often precisely because I swear NO CHOICE of keyword would satisfy everybody! Most languages start with designated keywords and some reserve a few for later use. But then things can get frozen in place to avoid breaking existing programs or break older compilers/interpreters. > > > > Some languages use techniques to extend themselves more harmlessly such as creating a singleton object that has content that can be regular data as in math.pi, or functions/methods or new ides like "Symbols" that allow all kinds of extensions to the language in a fairly harmless way as no older program would likely have used features that did not exist. > > > > That might not easily solve this problem. But I wonder if reserving some kind of prefix might help, so anything like extension.0nNoBreak could be added to a loop as a final clause and be treated as a non-key keyword of sorts. > > My idea would be to reserve different unicode blocks for the keywords > and the identifiers. e.g. We could reserve the mathematical alphanumeric > block for keywords and all other letters and numbers for identifiers. > Doing so would allow extenting the keywords without breaking programs > that already use that combination as an identifier. Python currently defines identifiers as follows: https://docs.python.org/3/reference/lexical_analysis.html#identifiers Briefly, what it means is that (aside from some backward compatibility special cases) an identifier contains letters, numbers, and connector punctuation, and must not start with a number. It's not by blocks, it's by types. It's way WAY too late to change what's allowed for identifiers, as you will potentially be breaking programs that use the current rules. > Python could slowly transition in this direction by first allowing the > current keywords to be in this block. Every new keyword would only be in > that unicode block. If would then be possible to write python code with > this convention but it wouldn't be obligatory. After some time the > python developers could decide to make it obligatory. Obligatory??? Please explain how you intend to convince the entire world that non-ASCII code is an acceptable requirement. Explain to me how you're going to go to every text editor and ensure that it supports easy entry of Python keywords that aren't ASCII. And please explain how this is even better. > I doubt this will idea will get from the ground, but I think it would > allow for a smoother transition into new concepts, as it is no longer a > strugle searching for a keyword that will break as little programs as > possible. Yeah it won't. Good luck though. ChrisA From antoon.pardon at vub.be Sun Oct 16 07:45:36 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 13:45:36 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Message-ID: <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> Op 16/10/2022 om 13:03 schreef Chris Angelico: > On Sun, 16 Oct 2022 at 21:19, Antoon Pardon wrote: > >> My idea would be to reserve different unicode blocks for the keywords >> and the identifiers. e.g. We could reserve the mathematical alphanumeric >> block for keywords and all other letters and numbers for identifiers. >> Doing so would allow extenting the keywords without breaking programs >> that already use that combination as an identifier. > Python currently defines identifiers as follows: > https://docs.python.org/3/reference/lexical_analysis.html#identifiers > > Briefly, what it means is that (aside from some backward compatibility > special cases) an identifier contains letters, numbers, and connector > punctuation, and must not start with a number. It's not by blocks, > it's by types. > > It's way WAY too late to change what's allowed for identifiers, as you > will potentially be breaking programs that use the current rules. So? Python has broken backward compatibility before. The cost could be acceptable. How many programs do you estimated use the mathematical alphanumeric block for an identifier at this moment? >> Python could slowly transition in this direction by first allowing the >> current keywords to be in this block. Every new keyword would only be in >> that unicode block. If would then be possible to write python code with >> this convention but it wouldn't be obligatory. After some time the >> python developers could decide to make it obligatory. > Obligatory??? Please explain how you intend to convince the entire > world that non-ASCII code is an acceptable requirement. Explain to me > how you're going to go to every text editor and ensure that it > supports easy entry of Python keywords that aren't ASCII. And please > explain how this is even better. Why should I do that? It seems you have already made your mind up. That is fine. It just makes explaining not very senseful. >> I doubt this will idea will get from the ground, but I think it would >> allow for a smoother transition into new concepts, as it is no longer a >> strugle searching for a keyword that will break as little programs as >> possible. > Yeah it won't. Good luck though. Why would I need good luck? I expressed an idea and you didn't like it. That won't affect my life in a meaningful way. -- Antoon Pardon. From avi.e.gross at gmail.com Sun Oct 16 11:03:02 2022 From: avi.e.gross at gmail.com (Avi Gross) Date: Sun, 16 Oct 2022 11:03:02 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Message-ID: Interesting idea, Anton. I would be interested in hearing more detail on how it would work. Although much of programming has been centered on the Latin alphabet and especially English, that may change. I can imagine a customized compiler or interpreter that uses key words in the local language instead of for or while or if or else or even import. If a region of UNICODE was set aside, would it have to be as a sort of additional ALT or shift key for anything, or just English characters or would it be for abstract symbols that would be mapped to and from a long list of reserved key words that may vary by locale? A serious problem I have been noting is the interactions between typographical paradigms never expected to interact. I mean special characters allowed or expected that clash. An example in Python and many other languages is regular expressions. When using a string of characters, you may have to deal with the rules for evaluating a string of that type and double up backslash characters or be carefully as a dollar sign or curly brace might invoke a side effect and interpolate something into it. But for languages that allow RE to be entered without a string as in /.../ you have to write it differently. I noted other ways in which naming conventions and even sort of keywords need special care. Consider a Javascript program in a browser that can read and manipulate HTML and CSS. The rules for names in JS do not allow hyphens while others often do. So the programmers making the structures in the DOM had to twist things. To access something like font-type you ask for font Type as an example by changing the identifier to camel case. I sometimes have programs that combine R and Python somewhat interchangeably and it highlights places the naming does not match. R allows periods as parts of names as in my.data and almost anything including spaces if you use grave accent quotes such as `one [identifier` so it is perfectly valid to have a function call like `[`(x, 5) to mean x[5] albeit explaining why that is useful is beyond the scope. Similarly you can make all kinds of in-line functions between percent signs as in %*% or %specialized computation% and you sort of make your own keywords albeit Chris and others may rightly suggest they are something else rather than the first level of syntax. My point is that your idea may need to support keywords for disparate ideas and languages. On Sun, Oct 16, 2022, 6:20 AM Antoon Pardon wrote: > Op 16/10/2022 om 00:50 schreef avi.e.gross at gmail.com: > > This has been discussed so often precisely because I swear NO CHOICE of > keyword would satisfy everybody! Most languages start with designated > keywords and some reserve a few for later use. But then things can get > frozen in place to avoid breaking existing programs or break older > compilers/interpreters. > > > > Some languages use techniques to extend themselves more harmlessly such > as creating a singleton object that has content that can be regular data as > in math.pi, or functions/methods or new ides like "Symbols" that allow all > kinds of extensions to the language in a fairly harmless way as no older > program would likely have used features that did not exist. > > > > That might not easily solve this problem. But I wonder if reserving some > kind of prefix might help, so anything like extension.0nNoBreak could be > added to a loop as a final clause and be treated as a non-key keyword of > sorts. > > My idea would be to reserve different unicode blocks for the keywords > and the identifiers. e.g. We could reserve the mathematical alphanumeric > block for keywords and all other letters and numbers for identifiers. > Doing so would allow extenting the keywords without breaking programs > that already use that combination as an identifier. > > Python could slowly transition in this direction by first allowing the > current keywords to be in this block. Every new keyword would only be in > that unicode block. If would then be possible to write python code with > this convention but it wouldn't be obligatory. After some time the > python developers could decide to make it obligatory. > > I doubt this will idea will get from the ground, but I think it would > allow for a smoother transition into new concepts, as it is no longer a > strugle searching for a keyword that will break as little programs as > possible. > > -- > Antoon Pardon. > -- > https://mail.python.org/mailman/listinfo/python-list > From rosuav at gmail.com Sun Oct 16 11:05:58 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 17 Oct 2022 02:05:58 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> Message-ID: On Sun, 16 Oct 2022 at 22:47, Antoon Pardon wrote: > > > > Op 16/10/2022 om 13:03 schreef Chris Angelico: > > On Sun, 16 Oct 2022 at 21:19, Antoon Pardon wrote: > > > >> My idea would be to reserve different unicode blocks for the keywords > >> and the identifiers. e.g. We could reserve the mathematical alphanumeric > >> block for keywords and all other letters and numbers for identifiers. > >> Doing so would allow extenting the keywords without breaking programs > >> that already use that combination as an identifier. > > Python currently defines identifiers as follows: > > https://docs.python.org/3/reference/lexical_analysis.html#identifiers > > > > Briefly, what it means is that (aside from some backward compatibility > > special cases) an identifier contains letters, numbers, and connector > > punctuation, and must not start with a number. It's not by blocks, > > it's by types. > > > > It's way WAY too late to change what's allowed for identifiers, as you > > will potentially be breaking programs that use the current rules. > > So? Python has broken backward compatibility before. The cost could > be acceptable. How many programs do you estimated use the mathematical > alphanumeric block for an identifier at this moment? > Why would I need good luck? I expressed an idea and you didn't like it. > That won't affect my life in a meaningful way. Well, with that attitude, it's not going to affect anyone else's life either, so go ahead, carry on. ChrisA From barry at barrys-emacs.org Sun Oct 16 12:21:03 2022 From: barry at barrys-emacs.org (Barry) Date: Sun, 16 Oct 2022 17:21:03 +0100 Subject: Find the path of a shell command [POSTPONED] In-Reply-To: References: Message-ID: > On 16 Oct 2022, at 04:53, Dan Stromberg wrote: > > ?On Wed, Oct 12, 2022 at 9:57 PM Cameron Simpson wrote: > >>> On 13Oct2022 03:25, Paulo da Silva >>> wrote: >>> There is another problem involved. The script, works fine except when >>> launched by cron! Why? >> >> Record the script output: >> >> # record all output >> exec >/tmp/script.$$.out 2>&1 >> # dump the envionment >> env | sort >> # turn on execution tracing >> set -x >> ... rest of the script >> >> and have a look afterwards. Cron's environment is very minimal. This >> will show you what's in it. >> > > Careful. On some systems if someone restarts the cron daemon, it could > pick up a larger environment than after being started on boot. That have to a old system that does not use systemd. Is there a specific system that still does this? Barry > -- > https://mail.python.org/mailman/listinfo/python-list > From antoon.pardon at vub.be Sun Oct 16 12:55:59 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 18:55:59 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> Message-ID: <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> Op 16/10/2022 om 17:05 schreef Chris Angelico: > On Sun, 16 Oct 2022 at 22:47, Antoon Pardon wrote: >> Why would I need good luck? I expressed an idea and you didn't like it. >> That won't affect my life in a meaningful way. > Well, with that attitude, it's not going to affect anyone else's life > either, so go ahead, carry on. What attitude? I just floated a little idea. It was not meant/expected to affect anyone else's life. So why do you react as if it was? -- Antoon Pardon From hjp-python at hjp.at Sun Oct 16 13:01:03 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 16 Oct 2022 19:01:03 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Message-ID: <20221016170103.htj57q43ux5lqzy5@hjp.at> On 2022-10-16 12:17:39 +0200, Antoon Pardon wrote: > Op 16/10/2022 om 00:50 schreef avi.e.gross at gmail.com: > > That might not easily solve this problem. But I wonder if reserving > > some kind of prefix might help, so anything like extension.0nNoBreak > > could be added to a loop as a final clause and be treated as a > > non-key keyword of sorts. > > My idea would be to reserve different unicode blocks for the keywords and > the identifiers. e.g. We could reserve the mathematical alphanumeric block > for keywords and all other letters and numbers for identifiers. Doing so > would allow extenting the keywords without breaking programs that already > use that combination as an identifier. Or you could go back to the old Algol idea of underlining keywords. Both have the same problem, though: They make editing with an ordinary text editor pretty much impossible. You need a language-aware IDE which makes entering these characters or markups simple. Maybe even a specialized keyboard like they had for APL (or the Sinclair ZX computers which had special combinations for all the BASIC keywords). And if you go this way, why not go a step further and dissociate the program from its linear text representation? Add footnotes, different views, hyperlinks, format mathematical expressions like formulas, etc. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From rosuav at gmail.com Sun Oct 16 13:03:53 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 17 Oct 2022 04:03:53 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> Message-ID: On Mon, 17 Oct 2022 at 03:57, Antoon Pardon wrote: > > > Op 16/10/2022 om 17:05 schreef Chris Angelico: > > On Sun, 16 Oct 2022 at 22:47, Antoon Pardon wrote: > >> Why would I need good luck? I expressed an idea and you didn't like it. > >> That won't affect my life in a meaningful way. > > Well, with that attitude, it's not going to affect anyone else's life > > either, so go ahead, carry on. > > What attitude? I just floated a little idea. It was not meant/expected to > affect anyone else's life. So why do you react as if it was? > You expressed an idea that you would like to see implemented in Python, and part of that idea was that people would be *obliged* to write their code using non-ASCII keywords. If that were to be implemented, it absolutely WOULD affect many people's lives. So if you're saying that your idea was not meant to affect anyone else's life, you are saying that you floated the idea fully intending for it to be ignored, which makes me wonder why you posted it in the first place. ChrisA From python at mrabarnett.plus.com Sun Oct 16 13:01:06 2022 From: python at mrabarnett.plus.com (MRAB) Date: Sun, 16 Oct 2022 18:01:06 +0100 Subject: for -- else: what was the motivation? In-Reply-To: <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> Message-ID: On 2022-10-15 23:50, avi.e.gross at gmail.com wrote: > This has been discussed so often precisely because I swear NO CHOICE of keyword would satisfy everybody! Most languages start with designated keywords and some reserve a few for later use. But then things can get frozen in place to avoid breaking existing programs or break older compilers/interpreters. > > Some languages use techniques to extend themselves more harmlessly such as creating a singleton object that has content that can be regular data as in math.pi, or functions/methods or new ides like "Symbols" that allow all kinds of extensions to the language in a fairly harmless way as no older program would likely have used features that did not exist. > > That might not easily solve this problem. But I wonder if reserving some kind of prefix might help, so anything like extension.0nNoBreak could be added to a loop as a final clause and be treated as a non-key keyword of sorts. > If you'd accept 2 words: for child in tree.getroot(): if child.tag == 'server': break not break: raise ValueError(f"server tag not found in {lfile}") > -----Original Message----- > From: Python-list On Behalf Of Rob Cliffe via Python-list > Sent: Wednesday, October 12, 2022 6:20 PM > To: python-list at python.org > Subject: Re: for -- else: what was the motivation? > > I too have occasionally used for ... else. It does have its uses. But oh, how I wish it had been called something else more meaningful, whether 'nobreak' or whatever. It used to really confuse me. Now I've learned to mentally replace "else" by "if nobreak", it confuses me a bit less. > Rob Cliffe > > On 12/10/2022 22:11, Weatherby,Gerard wrote: >> As did I. >> >> tree = ET.parse(lfile) >> for child in tree.getroot(): >> if child.tag == 'server': >> break >> else: >> raise ValueError(f"server tag not found in {lfile}") >> >> I think there are other places I could be using it, but honestly I tend to forget it?s available. >> >> From: Python-list >> on behalf of Stefan Ram >> Date: Wednesday, October 12, 2022 at 2:22 PM >> To: python-list at python.org >> Subject: Re: for -- else: what was the motivation? >> *** Attention: This is an external email. Use caution responding, >> opening attachments or clicking on links. *** >> >> Axy writes: >>> So, seriously, why they needed else if the following pieces produce >>> same result? Does anyone know or remember their motivation? >> Just wrote code wherein I used "else"! This: >> >> import locale >> for name in( 'de', 'de_DE', 'deu_deu', 'deu', 'German', 'Deutsch' ): >> try: locale.setlocale( locale.LC_ALL, name ); break >> except locale.Error: pass >> else: print( "Programm kann deutsche Schreibweise nicht einrichten." ) >> >> . >> From hjp-python at hjp.at Sun Oct 16 13:16:34 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 16 Oct 2022 19:16:34 +0200 Subject: Find the path of a shell command [POSTPONED] In-Reply-To: References: Message-ID: <20221016171634.mzpznpeaumntaoep@hjp.at> On 2022-10-16 17:21:03 +0100, Barry wrote: > > On 16 Oct 2022, at 04:53, Dan Stromberg wrote: > > > > ?On Wed, Oct 12, 2022 at 9:57 PM Cameron Simpson wrote: > > > >>> On 13Oct2022 03:25, Paulo da Silva > >>> wrote: > >>> There is another problem involved. The script, works fine except when > >>> launched by cron! Why? [... script deleted ...] > >> Cron's environment is very minimal. This will show you what's in > >> it. > > > > Careful. On some systems if someone restarts the cron daemon, it could > > pick up a larger environment than after being started on boot. > > That have to a old system that does not use systemd. Systemd is specific to Linux - and not even used by all Linux distributions. > Is there a specific system that still does this? Not sure. Some Unixes I've used in the past (probably including some Linux distributions) had this problem. So you had to be a bit careful when restarting daemons from the command line. I think the sysVinit system used by most Linux distributions before systemd did clean up the environment if you used it correctly (but I'm not sure and have no system anymore to test it). I haven't used Solaris or HP/UX in a long time (and other Unixes even longer) so I don't know what they do these days. And I've never used MacOS, I just know that they've used a system of their own long before systemd. Anyway he doesn't have to restart cron to add a cron-job (nor for any other reason during normal operation), so what happens if you manually restart cron is almost certainly irrelevant for the OP. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From antoon.pardon at vub.be Sun Oct 16 13:37:59 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 19:37:59 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> Message-ID: <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> Op 16/10/2022 om 19:03 schreef Chris Angelico: > On Mon, 17 Oct 2022 at 03:57, Antoon Pardon wrote: >> >> Op 16/10/2022 om 17:05 schreef Chris Angelico: >>> On Sun, 16 Oct 2022 at 22:47, Antoon Pardon wrote: >>>> Why would I need good luck? I expressed an idea and you didn't like it. >>>> That won't affect my life in a meaningful way. >>> Well, with that attitude, it's not going to affect anyone else's life >>> either, so go ahead, carry on. >> What attitude? I just floated a little idea. It was not meant/expected to >> affect anyone else's life. So why do you react as if it was? >> > You expressed an idea that you would like to see implemented in > Python, and part of that idea was that people would be *obliged* to > write their code using non-ASCII keywords. If that were to be > implemented, it absolutely WOULD affect many people's lives. So what? I made it clear that was an if I didn't expect to happen. An idea that doesn't happen will not affect anyone, whatever the consequences tied to the idea. > So if > you're saying that your idea was not meant to affect anyone else's > life, you are saying that you floated the idea fully intending for it > to be ignored, which makes me wonder why you posted it in the first > place. People can find it interesting to discuss an idea, even if they think there is no chance the idea will be carried out. -- Antoon Pardon From antoon.pardon at vub.be Sun Oct 16 13:43:32 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 19:43:32 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> Message-ID: <0b60ac78-02b5-77a2-3d41-12b64c7815b4@vub.be> Op 16/10/2022 om 17:03 schreef Avi Gross: > Interesting idea, Anton. > > I would be interested in hearing more detail on how it would work. > > Although much of programming has been centered on the Latin alphabet > and especially English, that may change. I can imagine a customized > compiler or interpreter that uses key words in the local language > instead of for or while or if or else or even import. > > If a region of UNICODE was set aside, would it have to be as a sort of > additional ALT or shift key for anything, or just English characters > or would it be for abstract symbols that would be mapped to and from a > long list of reserved key words that may vary by locale? I think you are carrying my idea further than I intended. I was just thinking that instead of using U+0064 U+0065 U+0066 [beinf def] we could be using U+1D41D U+1D41E U+1D41F [being? ???]. -- Antoon Pardon. From antoon.pardon at vub.be Sun Oct 16 13:52:47 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Sun, 16 Oct 2022 19:52:47 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <20221016170103.htj57q43ux5lqzy5@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> Message-ID: <35055568-755b-3bff-a0d8-176d09fb9586@vub.be> Op 16/10/2022 om 19:01 schreef Peter J. Holzer: > On 2022-10-16 12:17:39 +0200, Antoon Pardon wrote: >> Op 16/10/2022 om 00:50 schreefavi.e.gross at gmail.com: >>> That might not easily solve this problem. But I wonder if reserving >>> some kind of prefix might help, so anything like extension.0nNoBreak >>> could be added to a loop as a final clause and be treated as a >>> non-key keyword of sorts. >> My idea would be to reserve different unicode blocks for the keywords and >> the identifiers. e.g. We could reserve the mathematical alphanumeric block >> for keywords and all other letters and numbers for identifiers. Doing so >> would allow extenting the keywords without breaking programs that already >> use that combination as an identifier. > Or you could go back to the old Algol idea of underlining keywords. > > Both have the same problem, though: They make editing with an ordinary > text editor pretty much impossible. You need a language-aware IDE which > makes entering these characters or markups simple. That is not true with my idea. The editor would just need to be able to work with unicode characters. Vim can work with ??? just as it can with def. In vim I can also define abbreviations so that whenever I type ^Bd vim wil insert ??? for me. It may be useful to have an alternative keyboard definition ready to easily insert these characters into the editor but ordinary editors should already be able to treat these characters as any other unicode character. -- Antoon Pardon From axy at declassed.art Sun Oct 16 13:52:39 2022 From: axy at declassed.art (Axy) Date: Sun, 16 Oct 2022 18:52:39 +0100 Subject: for -- else: what was the motivation? In-Reply-To: <0b60ac78-02b5-77a2-3d41-12b64c7815b4@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <0b60ac78-02b5-77a2-3d41-12b64c7815b4@vub.be> Message-ID: <4c1a1d34-d295-8df8-7df6-b124ee68dfc5@declassed.art> On 16/10/2022 18:43, Antoon Pardon wrote: > Op 16/10/2022 om 17:03 schreef Avi Gross: >> Interesting idea, Anton. >> >> I would be interested in hearing more detail on how it would work. >> >> Although much of programming has been centered on the Latin alphabet >> and especially English, that may change. I can imagine a customized >> compiler or interpreter that uses key words in the local language >> instead of for or while or if or else or even import. Please, please please... forget about that idea. I know examples. They had no future, and have no future. Either RMS or ESR once have written in one of their book: "Please write in C". Same here: please speak in English. Although, if you like that idea who can stop you? In such a case I vote for ??????? Axy. From hjp-python at hjp.at Sun Oct 16 16:26:50 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 16 Oct 2022 22:26:50 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <35055568-755b-3bff-a0d8-176d09fb9586@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> <35055568-755b-3bff-a0d8-176d09fb9586@vub.be> Message-ID: <20221016202650.6sl457lfj5fflmh2@hjp.at> On 2022-10-16 19:52:47 +0200, Antoon Pardon wrote: > Op 16/10/2022 om 19:01 schreef Peter J. Holzer: > > On 2022-10-16 12:17:39 +0200, Antoon Pardon wrote: > > > Op 16/10/2022 om 00:50 schreefavi.e.gross at gmail.com: > > > > That might not easily solve this problem. But I wonder if reserving > > > > some kind of prefix might help, so anything like extension.0nNoBreak > > > > could be added to a loop as a final clause and be treated as a > > > > non-key keyword of sorts. > > > My idea would be to reserve different unicode blocks for the keywords and > > > the identifiers. e.g. We could reserve the mathematical alphanumeric block > > > for keywords and all other letters and numbers for identifiers. Doing so > > > would allow extenting the keywords without breaking programs that already > > > use that combination as an identifier. > > Or you could go back to the old Algol idea of underlining keywords. > > > > Both have the same problem, though: They make editing with an ordinary > > text editor pretty much impossible. You need a language-aware IDE which > > makes entering these characters or markups simple. > > That is not true with my idea. The editor would just need to be able > to work with unicode characters. Vim can work with ??? just as it can > with def. Yes, vim can. But can the user? And the user's system? And vim isn't the only editor out there. So you need a system for every editor some Python programmer might want to use. While most will probably use a sufficiently powerful editor, some won't. > In vim I can also define abbreviations so that whenever I type ^Bd vim > wil insert ??? for me. Which requires the user to define and type abbreviations. Which may be hard if they can't enter the characters in the first place (Ok, that may not be a problem as most users will probably just install a package from the internet,) The same does work with underlines: d?e?f? although weirdly my terminal underlines the wrong characters (the one to the right instead of the one to the left). The pragmatic action would of course to define "def" as an abbreviation for "???" (or "d?e?f?"), but then what have you won? hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From avi.e.gross at gmail.com Sun Oct 16 17:21:17 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sun, 16 Oct 2022 17:21:17 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> Message-ID: <006301d8e1a5$3ada5430$b08efc90$@gmail.com> Realistically an idea about something new is easier to consider than changing what you have. Some newer languages may well be designed from the start in new ways and Julia is an example of a language that allows a wide swath of UNICODE characters to be used in identifiers. They also let you type them in even using ASCII keyboards for some level of compatibility. The original topic asked about the topic of re-using ELSE as a known keyword in a context I and some others feel is a stretch. But the alterative could be to add an ever increasing number of keywords to meet new needs. I had another crazy thought that I AM NOT ASKING anyone to do. OK? I was wondering about a sort of catch method you could use that generates a pseudo-signal only when the enclosed preceding loop exits normally as a sort of way to handle the ELSE need without the use of a keyword known by the language. All you would need is an object of the right kind that is thrown and optionally caught. Of course, even if I fleshed this out and even if anyone thought it made sense, there is no such need now as Python has made a choice that meets the need even if few may dare use it or even know about it! LOL! -----Original Message----- From: Python-list On Behalf Of Antoon Pardon Sent: Sunday, October 16, 2022 1:38 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? Op 16/10/2022 om 19:03 schreef Chris Angelico: > On Mon, 17 Oct 2022 at 03:57, Antoon Pardon wrote: >> >> Op 16/10/2022 om 17:05 schreef Chris Angelico: >>> On Sun, 16 Oct 2022 at 22:47, Antoon Pardon wrote: >>>> Why would I need good luck? I expressed an idea and you didn't like it. >>>> That won't affect my life in a meaningful way. >>> Well, with that attitude, it's not going to affect anyone else's >>> life either, so go ahead, carry on. >> What attitude? I just floated a little idea. It was not >> meant/expected to affect anyone else's life. So why do you react as if it was? >> > You expressed an idea that you would like to see implemented in > Python, and part of that idea was that people would be *obliged* to > write their code using non-ASCII keywords. If that were to be > implemented, it absolutely WOULD affect many people's lives. So what? I made it clear that was an if I didn't expect to happen. An idea that doesn't happen will not affect anyone, whatever the consequences tied to the idea. > So if > you're saying that your idea was not meant to affect anyone else's > life, you are saying that you floated the idea fully intending for it > to be ignored, which makes me wonder why you posted it in the first > place. People can find it interesting to discuss an idea, even if they think there is no chance the idea will be carried out. -- Antoon Pardon -- https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Sun Oct 16 18:55:34 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 17 Oct 2022 09:55:34 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <006301d8e1a5$3ada5430$b08efc90$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> Message-ID: On Mon, 17 Oct 2022 at 08:22, wrote: > I had another crazy thought that I AM NOT ASKING anyone to do. OK? > Here's another proposal: Let's ban you from this mailing list. Don't worry, I AM NOT ASKING anyone to do it. OK? Do you see how ridiculous and pointless it is to have proposals with that kind of caveat? Make serious proposals that we can discuss reasonably, don't make fake proposals and hide behind a caveat. ChrisA From avi.e.gross at gmail.com Sun Oct 16 19:46:43 2022 From: avi.e.gross at gmail.com (avi.e.gross at gmail.com) Date: Sun, 16 Oct 2022 19:46:43 -0400 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> Message-ID: <007c01d8e1b9$8baa9000$a2ffb000$@gmail.com> My point Chris was that you can have a conversation where you are exploring and not proposing. Brainstorming, perhaps. I was saying that there are many ways to signal things and in some hypothetical new language, it may be implemented in novel ways that do not break anything. I note languages like JavaScript seem to love passing functions or setting event handlers that may only be activated under unusual conditions. So my POINT (and I repeat NOT a suggestion) is that I can IMAGINE ways to add a feature to a loop, such as an extra optional argument that is called if the loop exits from the bottom. The code you now put in the ELSE clause might have to be in the lambda or whatever. That may not be a good fit for Python. What may aggravate you is that lots of people keep telling you that the ELSE on a loop feature is not intuitive to many, sometimes even after it is explained. My suggestion is you should deal with that and not take it out on others. Live and let live. My view remains that something has been added and is available and won't likely be changed so use it as-is or ignore it. But if anyone wants to make their own language, they can feel free to design around this any way they wish. If they design an object that encapsulates a loop and then add attributes to the object that are guaranteed to tell you how the loop ended and run some code if it is set there, fine. This forum may be about Python but not exclusively. I personally often enjoy hearing how some other system does something similar, such as discussions on how and whether Python should allow an underscore in static numbers given other languages do so, not always identically. We can learn from such comparisons, for good and also for bad. I am NOT proposing we change anything about ELSE and that was not my point. My point was that sometimes rather than reuse an existing keyword in the language or create new reserved keywords, there can be many possible ways to extend functionality. I know of languages with multiple variations on loops that do not break existing code. If your syntax is for (...) { ...} then if you add the ability to place some identifier ONLY in the context involved then for XXX (...) { ...} may mean some altered functionality while YYY in the same spot means something else and the original form continues to do what it always did. So are XXX and YYY keywords or something else? Again, I do not understand why people here get so touchy. But if it makes you happy, take me off this list! I have so many things I need to do and free up time for. -----Original Message----- From: Python-list On Behalf Of Chris Angelico Sent: Sunday, October 16, 2022 6:56 PM To: python-list at python.org Subject: Re: for -- else: what was the motivation? On Mon, 17 Oct 2022 at 08:22, wrote: > I had another crazy thought that I AM NOT ASKING anyone to do. OK? > Here's another proposal: Let's ban you from this mailing list. Don't worry, I AM NOT ASKING anyone to do it. OK? Do you see how ridiculous and pointless it is to have proposals with that kind of caveat? Make serious proposals that we can discuss reasonably, don't make fake proposals and hide behind a caveat. ChrisA -- https://mail.python.org/mailman/listinfo/python-list From rosuav at gmail.com Sun Oct 16 22:01:16 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 17 Oct 2022 13:01:16 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <007c01d8e1b9$8baa9000$a2ffb000$@gmail.com> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> <007c01d8e1b9$8baa9000$a2ffb000$@gmail.com> Message-ID: On Mon, 17 Oct 2022 at 10:46, wrote: > > My point Chris was that you can have a conversation where you are exploring > and not proposing. Brainstorming, perhaps. And my point is that either a proposal is a serious one that can expect serious discussion, or it isn't. Yes, I'm aware that it wasn't you who backpedalled as soon as any criticism was posted, but your caveat comes to the same thing - if you're trying to avoid serious criticism, you have to not post an idea. > So my POINT (and I repeat NOT a suggestion) is that I can IMAGINE ways to > add a feature to a loop, such as an extra optional argument that is called > if the loop exits from the bottom. The code you now put in the ELSE clause > might have to be in the lambda or whatever. That may not be a good fit for > Python. If you're inventing a completely new language, you can do whatever you like, but it's not very practical to discuss small features when there's no language to discuss them in. So are you discussing this as a Python feature, or just saying "hey, in a vacuum, we could do this", which is vacuously true? > What may aggravate you is that lots of people keep telling you that the ELSE > on a loop feature is not intuitive to many, sometimes even after it is > explained. I know it's unintuitive. That doesn't stop it being useful. > My suggestion is you should deal with that and not take it out on others. > Live and let live. That's unrelated. Sorry to disappoint you. > This forum may be about Python but not exclusively. I personally often enjoy > hearing how some other system does something similar, such as discussions on > how and whether Python should allow an underscore in static numbers given > other languages do so, not always identically. We can learn from such > comparisons, for good and also for bad. That's correct, but usually there's at least SOME context. And if none is given, is it or is it not reasonable to assume that people are talking about Python? > But if it makes you happy, take me off this list! I have so many things I > need to do and free up time for. I'm not in a position to do that, and my point was to show how ridiculous empty proposals are :) ChrisA From antoon.pardon at vub.be Mon Oct 17 01:34:50 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Mon, 17 Oct 2022 07:34:50 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> <007c01d8e1b9$8baa9000$a2ffb000$@gmail.com> Message-ID: Op 17/10/2022 om 04:01 schreef Chris Angelico: > On Mon, 17 Oct 2022 at 10:46, wrote: >> My point Chris was that you can have a conversation where you are exploring >> and not proposing. Brainstorming, perhaps. > And my point is that either a proposal is a serious one that can > expect serious discussion, or it isn't. Yes, I'm aware that it wasn't > you who backpedalled as soon as any criticism was posted, but your > caveat comes to the same thing - if you're trying to avoid serious > criticism, you have to not post an idea. Your reaction was not serious criticisme but a belligerent reaction. You made it clear you wanted a fight. I choose not to enter that fight. -- Antoon Pardon From rosuav at gmail.com Mon Oct 17 02:21:24 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 17 Oct 2022 17:21:24 +1100 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> <007c01d8e1b9$8baa9000$a2ffb000$@gmail.com> Message-ID: On Mon, 17 Oct 2022 at 16:36, Antoon Pardon wrote: > > > > Op 17/10/2022 om 04:01 schreef Chris Angelico: > > On Mon, 17 Oct 2022 at 10:46, wrote: > >> My point Chris was that you can have a conversation where you are exploring > >> and not proposing. Brainstorming, perhaps. > > And my point is that either a proposal is a serious one that can > > expect serious discussion, or it isn't. Yes, I'm aware that it wasn't > > you who backpedalled as soon as any criticism was posted, but your > > caveat comes to the same thing - if you're trying to avoid serious > > criticism, you have to not post an idea. > > Your reaction was not serious criticisme but a belligerent reaction. > You made it clear you wanted a fight. I choose not to enter that > fight. > Well, if reacting strongly to a proposal to break LITERALLY EVERY PYTHON PROGRAM EVER counts as not a serious criticism but a belligerent reaction, then there's not really a lot of point discussing further. Bye. ChrisA From Karsten.Hilbert at gmx.net Mon Oct 17 03:25:00 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Mon, 17 Oct 2022 09:25:00 +0200 Subject: Aw: Re: for -- else: what was the motivation? In-Reply-To: <20221016170103.htj57q43ux5lqzy5@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> Message-ID: > which had special combinations for all the BASIC keywords). And if you > go this way, why not go a step further and dissociate the program from > its linear text representation? Add footnotes, different views, > hyperlinks, format mathematical expressions like formulas, etc. http://literateprogramming.com/ Karsten From abderrahim.adrabi at gmail.com Sun Oct 16 06:48:45 2022 From: abderrahim.adrabi at gmail.com (Abderrahim Adrabi) Date: Sun, 16 Oct 2022 11:48:45 +0100 Subject: Optional arguments in a class behave like class attributes. Message-ID: Hi all, I tried to create a class with some optional arguments as always, but this time I used the default values to be lists, dictionaries, and object references. So, these default values behave like class attributes, here is a demo: # Using a list ----------------------------- class GameOne: def __init__(self, games = []) -> None: self.games = games h = GameOne() h.games.append("List, the first round") g = GameOne() g.games.append("List, the second round") k = GameOne() print('Using a list', k.games) # Using a dictionary -------------------------- class GameTwo: def __init__(self, games = {}) -> None: self.games = games h = GameTwo() h.games['1er'] = "Dictionary, the first round" g = GameTwo() g.games['2ed'] = "Dictionary, the second round" k = GameTwo() print('Using a dictionary', k.games) # Using an object ------------------------------ class Bonus: def __init__(self) -> None: self.stages = [] class GameThree: def __init__(self, bonus = Bonus()) -> None: self.bonus = bonus h = GameThree() h.bonus.stages.append('Object, the first round') g = GameThree() g.bonus.stages.append('Object, the second round') k = GameThree() print('Using an object', k.bonus.stages) # Results ---------------------------------------- Using a list ['List, the first round', 'List, the second round'] Using a dictionary {'1er': 'Dictionary, the first round', '2ed': 'Dictionary, the second round'} Using an object ['Object, the first round', 'Object, the second round'] # Used Python versions --------------------------- 3.5.1 (default, Dec 9 2015, 14:41:32) [GCC 5.2.0] 3.7.14 (default, Sep 8 2022, 00:06:44) [GCC 7.5.0] 3.8.6 (default, Jan 29 2021, 17:38:16) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)] 3.9.9 (main, Nov 20 2021, 21:30:06) [GCC 11.1.0] My question: Is this normal behavior? Thanks. From nospam at dfs.com Fri Oct 14 18:25:23 2022 From: nospam at dfs.com (DFS) Date: Fri, 14 Oct 2022 18:25:23 -0400 Subject: Quick question about CPython interpreter Message-ID: --------------------------------------------------------------------- this does a str() conversion in the loop --------------------------------------------------------------------- for i in range(cells.count()): if text == str(ID): break --------------------------------------------------------- this does one str() conversion before the loop --------------------------------------------------------- strID = str(ID) for i in range(cells.count()): if text == strID: break But does CPython interpret the str() conversion away and essentially do it for me in the first example? From a_eder_muc at web.de Sat Oct 15 12:13:32 2022 From: a_eder_muc at web.de (Andreas Eder) Date: Sat, 15 Oct 2022 18:13:32 +0200 Subject: Find the path of a shell command References: Message-ID: <87o7udt68j.fsf@eder.anydns.info> On Mi 12 Okt 2022 at 05:00, Paulo da Silva wrote: > The simple question: How do I find the full path of a shell command > (linux), i.e. how do I obtain the corresponding of, for example, > "type rm" in command line? > > The reason: > I have python program that launches a detached rm. It works pretty well > until it is invoked by cron! I suspect that for cron we need to specify > the full path. > Of course I can hardcode /usr/bin/rm. But, is rm always in /usr/bin? > What about other commands? Why not just use os.unlink ? 'Andreas From wlfraed at ix.netcom.com Sat Oct 15 12:31:11 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sat, 15 Oct 2022 12:31:11 -0400 Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> Message-ID: On Wed, 12 Oct 2022 23:19:39 +0100, Rob Cliffe declaimed the following: >I too have occasionally used for ... else.? It does have its uses. But >oh, how I wish it had been called something else more meaningful, >whether 'nobreak' or whatever.? It used to really confuse me.? Now I've "expired"? -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From boblatest at yahoo.com Mon Oct 17 07:49:39 2022 From: boblatest at yahoo.com (Robert Latest) Date: 17 Oct 2022 11:49:39 GMT Subject: for -- else: what was the motivation? References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <9c092db3-d3d9-cf09-8d16-9248b0944126@vub.be> <4a3cbc9a-d70b-27f5-9dda-14f59b7f68ce@vub.be> <86212e83-a53e-f260-27c9-76743fb7eaa5@vub.be> <006301d8e1a5$3ada5430$b08efc90$@gmail.com> Message-ID: wrote: > I had another crazy thought that I AM NOT ASKING anyone to do. OK? > > I was wondering about a sort of catch method you could use that generates a > pseudo-signal only when the enclosed preceding loop exits normally as a > sort of way to handle the ELSE need without the use of a keyword known by > the language. All you would need is an object of the right kind that is > thrown and optionally caught. (untested) try: while condition: if not do_something(): raise RuntimeError except RuntimeError: pass else: print('Loop exited normally') Ironically, this again relies on the much-used "else" and adds the overhead of exception handling. Also from a natural language perspective I find the "try ... except ... else" clause just as questionable as "while ... else." Since we're discussing weird keywords: Maybe we can find another use for "finally." In fact, one could argue that "while ... finally" could make just as much sense as "while ... else" (but I won't). > Of course, even if I fleshed this out and even if anyone thought it made > sense, there is no such need now as Python has made a choice that meets the > need even if few may dare use it or even know about it! LOL! From syedarshi at gmail.com Mon Oct 17 07:57:45 2022 From: syedarshi at gmail.com (Arshi Syed) Date: Mon, 17 Oct 2022 04:57:45 -0700 (PDT) Subject: Using Paramiko to submit job on SGE Message-ID: Hi All, I am trying to run a script-1 on a Linux server using a Paramiko ssh connection and this script-1 calls script-2 which ultimately submits a job using a qsub command, job starts on SGE and I can see it through qstat but everything stops as soon as the script-1 stops. It seems the SSH session is getting closed after script-1 execution. Could any one of you help me in resolving this issue? Thanks, SAUZ From rosuav at gmail.com Mon Oct 17 10:57:13 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 18 Oct 2022 01:57:13 +1100 Subject: Optional arguments in a class behave like class attributes. In-Reply-To: References: Message-ID: On Tue, 18 Oct 2022 at 01:39, Abderrahim Adrabi wrote: > So, these default values behave like class attributes, here is a demo: > > # Using a list ----------------------------- > class GameOne: > def __init__(self, games = []) -> None: > self.games = games > This makes the default be a single list, the same list for all of them. If you want the default to be "construct a new list", you'll need something else: def __init__(self, games=None): if games is None: games = [] There is an open proposal to allow this syntax, which would do what you want: def __init__(self, games=>[]): However, this is not part of any current version of Python. ChrisA From torriem at gmail.com Mon Oct 17 11:38:56 2022 From: torriem at gmail.com (Michael Torrie) Date: Mon, 17 Oct 2022 09:38:56 -0600 Subject: Quick question about CPython interpreter In-Reply-To: References: Message-ID: <930918a6-556f-2cdf-710b-e333703a9ca6@gmail.com> On 10/14/22 16:25, DFS wrote: > --------------------------------------------------------------------- > this does a str() conversion in the loop > --------------------------------------------------------------------- > for i in range(cells.count()): > if text == str(ID): > break > > > --------------------------------------------------------- > this does one str() conversion before the loop > --------------------------------------------------------- > strID = str(ID) > for i in range(cells.count()): > if text == strID: > break > > > But does CPython interpret the str() conversion away and essentially do > it for me in the first example? No. You can use the dis module to show you what CPython is doing under the hood. From david at lowryduda.com Mon Oct 17 11:43:59 2022 From: david at lowryduda.com (David Lowry-Duda) Date: Mon, 17 Oct 2022 11:43:59 -0400 Subject: Quick question about CPython interpreter In-Reply-To: References: Message-ID: One can use the `dis` module and investigate the generated python bytecode. For me, I get # file "dis1.py" thing = 123 for i in range(10): if "hi" == str(thing): print("found") break The bytecode is then 1 0 LOAD_CONST 0 (123) 2 STORE_NAME 0 (thing) 2 4 LOAD_NAME 1 (range) 6 LOAD_CONST 1 (10) 8 CALL_FUNCTION 1 10 GET_ITER >> 12 FOR_ITER 28 (to 42) 14 STORE_NAME 2 (i) 3 16 LOAD_CONST 2 ('hi') 18 LOAD_NAME 3 (str) 20 LOAD_NAME 0 (thing) 22 CALL_FUNCTION 1 24 COMPARE_OP 2 (==) 26 POP_JUMP_IF_FALSE 12 4 28 LOAD_NAME 4 (print) 30 LOAD_CONST 3 ('found') 32 CALL_FUNCTION 1 34 POP_TOP 5 36 POP_TOP 38 JUMP_ABSOLUTE 42 40 JUMP_ABSOLUTE 12 >> 42 LOAD_CONST 4 (None) 44 RETURN_VALUE I note that line 22 calls the function str repeatedly, and no optimization is done here. # file "dis2.py" thing = 123 strthing = str(thing) for i in range(10): if "hi" == strthing: print("found") break This generates bytecode 1 0 LOAD_CONST 0 (123) 2 STORE_NAME 0 (thing) 2 4 LOAD_NAME 1 (str) 6 LOAD_NAME 0 (thing) 8 CALL_FUNCTION 1 10 STORE_NAME 2 (strthing) 3 12 LOAD_NAME 3 (range) 14 LOAD_CONST 1 (10) 16 CALL_FUNCTION 1 18 GET_ITER >> 20 FOR_ITER 24 (to 46) 22 STORE_NAME 4 (i) 4 24 LOAD_CONST 2 ('hi') 26 LOAD_NAME 2 (strthing) 28 COMPARE_OP 2 (==) 30 POP_JUMP_IF_FALSE 20 5 32 LOAD_NAME 5 (print) 34 LOAD_CONST 3 ('found') 36 CALL_FUNCTION 1 38 POP_TOP 6 40 POP_TOP 42 JUMP_ABSOLUTE 46 44 JUMP_ABSOLUTE 20 >> 46 LOAD_CONST 4 (None) 48 RETURN_VALUE In short, it seems the cpython interpreter doesn't (currently) perform this sort of optimization. - DLD From python at mrabarnett.plus.com Mon Oct 17 12:25:34 2022 From: python at mrabarnett.plus.com (MRAB) Date: Mon, 17 Oct 2022 17:25:34 +0100 Subject: Quick question about CPython interpreter In-Reply-To: References: Message-ID: On 2022-10-17 16:43, David Lowry-Duda wrote: > One can use the `dis` module and investigate the generated python > bytecode. For me, I get > > # file "dis1.py" > thing = 123 > for i in range(10): > if "hi" == str(thing): > print("found") > break > > The bytecode is then > > 1 0 LOAD_CONST 0 (123) > 2 STORE_NAME 0 (thing) > > 2 4 LOAD_NAME 1 (range) > 6 LOAD_CONST 1 (10) > 8 CALL_FUNCTION 1 > 10 GET_ITER > >> 12 FOR_ITER 28 (to 42) > 14 STORE_NAME 2 (i) > > 3 16 LOAD_CONST 2 ('hi') > 18 LOAD_NAME 3 (str) > 20 LOAD_NAME 0 (thing) > 22 CALL_FUNCTION 1 > 24 COMPARE_OP 2 (==) > 26 POP_JUMP_IF_FALSE 12 > > 4 28 LOAD_NAME 4 (print) > 30 LOAD_CONST 3 ('found') > 32 CALL_FUNCTION 1 > 34 POP_TOP > > 5 36 POP_TOP > 38 JUMP_ABSOLUTE 42 > 40 JUMP_ABSOLUTE 12 > >> 42 LOAD_CONST 4 (None) > 44 RETURN_VALUE > > I note that line 22 calls the function str repeatedly, and no > optimization is done here. > > # file "dis2.py" > thing = 123 > strthing = str(thing) > for i in range(10): > if "hi" == strthing: > print("found") > break > > This generates bytecode > > 1 0 LOAD_CONST 0 (123) > 2 STORE_NAME 0 (thing) > > 2 4 LOAD_NAME 1 (str) > 6 LOAD_NAME 0 (thing) > 8 CALL_FUNCTION 1 > 10 STORE_NAME 2 (strthing) > > 3 12 LOAD_NAME 3 (range) > 14 LOAD_CONST 1 (10) > 16 CALL_FUNCTION 1 > 18 GET_ITER > >> 20 FOR_ITER 24 (to 46) > 22 STORE_NAME 4 (i) > > 4 24 LOAD_CONST 2 ('hi') > 26 LOAD_NAME 2 (strthing) > 28 COMPARE_OP 2 (==) > 30 POP_JUMP_IF_FALSE 20 > > 5 32 LOAD_NAME 5 (print) > 34 LOAD_CONST 3 ('found') > 36 CALL_FUNCTION 1 > 38 POP_TOP > > 6 40 POP_TOP > 42 JUMP_ABSOLUTE 46 > 44 JUMP_ABSOLUTE 20 > >> 46 LOAD_CONST 4 (None) > 48 RETURN_VALUE > > In short, it seems the cpython interpreter doesn't (currently) perform > this sort of optimization. > It can't optimise that because, say, 'print' could've been bound to a function that rebinds 'str'. From grant.b.edwards at gmail.com Mon Oct 17 13:55:08 2022 From: grant.b.edwards at gmail.com (Grant Edwards) Date: Mon, 17 Oct 2022 10:55:08 -0700 (PDT) Subject: Find the path of a shell command References: <87o7udt68j.fsf@eder.anydns.info> Message-ID: <634d96fc.920a0220.d035b.0835@mx.google.com> On 2022-10-15, Andreas Eder wrote: > On Mi 12 Okt 2022 at 05:00, Paulo da Silva wrote: > >> The simple question: How do I find the full path of a shell command >> (linux), i.e. how do I obtain the corresponding of, for example, >> "type rm" in command line? >> >> The reason: >> I have python program that launches a detached rm. It works pretty >> well until it is invoked by cron! I suspect that for cron we need >> to specify the full path. > Why not just use os.unlink ? Because he's using 'rm' to recursively remove a large directory tree many levels deep. One might think that could be done by os.removedirs(name) Remove directories recursively. [...] But it doesn't appear so from the description: Works like rmdir() except that, if the leaf directory is successfully removed, removedirs() tries to successively remove every parent directory mentioned in path until an error is raised (which is ignored, because it generally means that a parent directory is not empty). For example, os.removedirs('foo/bar/baz') will first remove the directory 'foo/bar/baz', and then remove 'foo/bar' and 'foo' if they are empty. Raises OSError if the leaf directory could not be successfully removed. From rosuav at gmail.com Mon Oct 17 13:59:05 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 18 Oct 2022 04:59:05 +1100 Subject: Quick question about CPython interpreter In-Reply-To: References: Message-ID: On Tue, 18 Oct 2022 at 03:51, Stefan Ram wrote: > > MRAB writes: > >It can't optimise that because, say, 'print' could've been bound to a > >function that rebinds 'str'. > > It would be possible to find out whether a call of a function > named "print" is to the standard function, but the overhead > to do this in the end might slow down the execution. > > In general, it can be possible that there could be optimizer > stages after compilation. So, one might write a small micro- > benchmark to be sure. > You'd also have to ensure that the stringification of the ID doesn't change (which it can it it isn't a core data type), and the easiest way to do THAT is to call str() on the ID every time and see if it's the same... ChrisA From antoon.pardon at vub.be Mon Oct 17 14:13:40 2022 From: antoon.pardon at vub.be (Antoon Pardon) Date: Mon, 17 Oct 2022 20:13:40 +0200 Subject: Optional arguments in a class behave like class attributes. In-Reply-To: References: Message-ID: <7a899996-c1fa-5b09-85ec-2c9cdd3e5495@vub.be> You can use the following decorator for what you probably want. def copy_defaults(func): """ This decorator makes that defaults values are copied on a call. """ signature = inspect.signature(func) parameter_items = list(signature.parameters.items()) @wraps(func) def wrapper(*args, **kwds): newargs = list(args) tail_parameters = parameter_items[len(args):] for name, parameter in tail_parameters: try: newargs.append(kwds[name]) del kwds[name] except KeyError: if parameter.default is not Parameter.empty: newargs.append(copy.deepcopy(parameter.default)) else: break return func(*newargs, **kwds) return wrapper class GameOne: @copy_defaults def __init__(self, games = []) -> None: self.games = games # Results I got after using this decorator in your code Using a list [] Using a dictionary {} Using an object [] Op 16/10/2022 om 12:48 schreef Abderrahim Adrabi: > Hi all, > > I tried to create a class with some optional arguments as always, but this > time I used the default values to be lists, dictionaries, and object > references. > > So, these default values behave like class attributes, here is a demo: > > # Using a list ----------------------------- > class GameOne: > def __init__(self, games = []) -> None: > self.games = games > > h = GameOne() > h.games.append("List, the first round") > > g = GameOne() > g.games.append("List, the second round") > > k = GameOne() > print('Using a list', k.games) > > # Using a dictionary -------------------------- > class GameTwo: > def __init__(self, games = {}) -> None: > self.games = games > > h = GameTwo() > h.games['1er'] = "Dictionary, the first round" > > g = GameTwo() > g.games['2ed'] = "Dictionary, the second round" > > k = GameTwo() > print('Using a dictionary', k.games) > > # Using an object ------------------------------ > class Bonus: > def __init__(self) -> None: > self.stages = [] > > class GameThree: > def __init__(self, bonus = Bonus()) -> None: > self.bonus = bonus > > h = GameThree() > h.bonus.stages.append('Object, the first round') > > g = GameThree() > g.bonus.stages.append('Object, the second round') > > k = GameThree() > print('Using an object', k.bonus.stages) > > # Results ---------------------------------------- > > Using a list ['List, the first round', 'List, the second round'] > Using a dictionary {'1er': 'Dictionary, the first round', '2ed': > 'Dictionary, the second round'} > Using an object ['Object, the first round', 'Object, the second round'] > > # Used Python versions --------------------------- > > 3.5.1 (default, Dec 9 2015, 14:41:32) > [GCC 5.2.0] > > 3.7.14 (default, Sep 8 2022, 00:06:44) > [GCC 7.5.0] > > 3.8.6 (default, Jan 29 2021, 17:38:16) > [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)] > > 3.9.9 (main, Nov 20 2021, 21:30:06) > [GCC 11.1.0] > > My question: Is this normal behavior? > > Thanks. From info at egenix.com Tue Oct 18 05:35:23 2022 From: info at egenix.com (eGenix Team) Date: Tue, 18 Oct 2022 11:35:23 +0200 Subject: ANN: PyDDF Python Herbst Sprint 2022 Message-ID: <037e023b-4cc1-795b-9add-18b50cc051fc@egenix.com> /This announcement is in German since it targets a local user group//meeting in D?sseldorf, Germany/ Ank?ndigung Python Meeting Herbst Sprint 2022 in D?sseldorf Samstag, 22.10.2022, 10:00-18:00 Uhr Sonntag, 23.10.2022, 10:00-18:00 Uhr /Atos Information Technology GmbH /, Am Seestern 1, 40547 D?sseldorf Informationen Das Python Meeting D?sseldorf (PyDDF) veranstaltet mit freundlicher Unterst?tzung der Atos Information Technology GmbH ein Python Sprint Wochenende. Der Sprint findet am Wochenende 22./23.10.2022 in der Atos Niederlassung, Am Seestern 1, in D?sseldorf statt. * Sprint Ort in Google Maps Folgende Themengebiete sind als Anregung bereits angedacht: * *Arbeiten mit Clusterfuzz * * *Python Workflow Tools (Airflow , Prefect , etc.)* Nat?rlich k?nnen die Teilnehmenden weitere Themen vorschlagen und umsetzen. Anmeldung, Kosten und weitere Infos Alles weitere und die Anmeldung findet Ihr auf der Meetup Sprint Seite: * *Python Herbst Sprint & Hackathon in D?sseldorf* *WICHTIG*: Ohne Anmeldung k?nnen wir den Geb?udezugang nicht vorbereiten. Eine spontane Anmeldung am Sprint Tag wird daher vermutlich nicht funktionieren. Also bitte unbedingt mit vollen Namen bis sp?testens am Freitag, 21.10., ?ber Meetup anmelden. Teilnehmer sollten sich zudem in der PyDDF Telegram Gruppe registrieren, da wir uns dort koordinieren: * *PyDDF Telegram Gruppe * ?ber das Python Meeting D?sseldorf Das Python Meeting D?sseldorf ist eine regelm??ige Veranstaltung in D?sseldorf, die sich an Python-Begeisterte aus der Region wendet. Einen guten ?berblick ?ber die Vortr?ge bietet unser PyDDF YouTube-Kanal , auf dem wir Videos der Vortr?ge nach den Meetings ver?ffentlichen. Veranstaltet wird das Meeting von der eGenix.com GmbH , Langenfeld, in Zusammenarbeit mit Clark Consulting & Research , D?sseldorf. Viel Spa? ! -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Experts (#1, Oct 18 2022) >>> Python Projects, Coaching and Support ... https://www.egenix.com/ >>> Python Product Development ... https://consulting.egenix.com/ ________________________________________________________________________ ::: We implement business ideas - efficiently in both time and costs ::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 https://www.egenix.com/company/contact/ https://www.malemburg.com/ From walshg at battelle.org Tue Oct 18 14:19:20 2022 From: walshg at battelle.org (Walsh, Ginny (US)) Date: Tue, 18 Oct 2022 18:19:20 +0000 Subject: Apparent Issue with Administrator Privileges In-Reply-To: <346aa6525a3348e8abf2d4d28bac1c67@battelle.org> References: <94708afdd86c4f1882a3f18686c9f03e@battelle.org> <374c2a60d281411e97aa512ade768419@battelle.org> <346aa6525a3348e8abf2d4d28bac1c67@battelle.org> Message-ID: <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> Hello- I've been struggling with resolving environmental variables issues and I believe it is linked to my company's administrator privileges. The program is called ChemPlugin and I am attempting to run it using Python 3.10.8 on Windows. I can't seem to get Python to recognize the PYTHONPATH that points to the ChemPlugin\src. I have to download ChemPlugin using my administrator login name, but Python is loaded to my local user profile. I can't seem to bridge the gap. I have been working with both the ChemPlugin group and our internal IT and we are all stumped. Is there any experience with this issue? Thanks, Ginny From jschwar at sbcglobal.net Tue Oct 18 15:51:15 2022 From: jschwar at sbcglobal.net (Jim Schwartz) Date: Tue, 18 Oct 2022 14:51:15 -0500 Subject: Apparent Issue with Administrator Privileges In-Reply-To: <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> References: <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> Message-ID: <9FB325E2-2417-481B-A017-9384A0AFF7D8@sbcglobal.net> Is PYTHONPATH a user defined environment variable or system defined environment variable? Sent from my iPhone > On Oct 18, 2022, at 1:56 PM, Walsh, Ginny (US) wrote: > > ?Hello- > > I've been struggling with resolving environmental variables issues and I believe it is linked to my company's administrator privileges. The program is called ChemPlugin and I am attempting to run it using Python 3.10.8 on Windows. I can't seem to get Python to recognize the PYTHONPATH that points to the ChemPlugin\src. I have to download ChemPlugin using my administrator login name, but Python is loaded to my local user profile. I can't seem to bridge the gap. > > I have been working with both the ChemPlugin group and our internal IT and we are all stumped. Is there any experience with this issue? > > Thanks, > > Ginny > -- > https://mail.python.org/mailman/listinfo/python-list From list1 at tompassin.net Tue Oct 18 16:09:31 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 18 Oct 2022 16:09:31 -0400 Subject: Apparent Issue with Administrator Privileges In-Reply-To: <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> References: <94708afdd86c4f1882a3f18686c9f03e@battelle.org> <374c2a60d281411e97aa512ade768419@battelle.org> <346aa6525a3348e8abf2d4d28bac1c67@battelle.org> <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> Message-ID: <8f20408b-eab2-4cd1-c1e9-e66b41ae5f61@tompassin.net> Looking at the ChemPlugin site, it looks like by default it would install into "C:\Program Files". Typically ordinary users do not have full privileges there, although they may have read privileges. If this is the case, either you would need to run it in an elevated (adminstrator) session, or try to reinstall it somewhere you do have privileges. You probably need to have write privileges too, since Python will try to write its compiled files into the same tree (but these files may have been created during installation so possibly not an issue). Re-installing it might require moving the license as well. Note that I have never used this product, so I don't have any personal experience about it to call on. On 10/18/2022 2:19 PM, Walsh, Ginny (US) wrote: > Hello- > > I've been struggling with resolving environmental variables issues and I believe it is linked to my company's administrator privileges. The program is called ChemPlugin and I am attempting to run it using Python 3.10.8 on Windows. I can't seem to get Python to recognize the PYTHONPATH that points to the ChemPlugin\src. I have to download ChemPlugin using my administrator login name, but Python is loaded to my local user profile. I can't seem to bridge the gap. > > I have been working with both the ChemPlugin group and our internal IT and we are all stumped. Is there any experience with this issue? > > Thanks, > > Ginny From list1 at tompassin.net Tue Oct 18 17:35:22 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 18 Oct 2022 17:35:22 -0400 Subject: Apparent Issue with Administrator Privileges In-Reply-To: <2a0a8b167e5145089348a368e9bdc283@battelle.org> References: <94708afdd86c4f1882a3f18686c9f03e@battelle.org> <374c2a60d281411e97aa512ade768419@battelle.org> <346aa6525a3348e8abf2d4d28bac1c67@battelle.org> <101f8f23b9f74ae8a85b96eafa376aba@battelle.org> <8f20408b-eab2-4cd1-c1e9-e66b41ae5f61@tompassin.net> <2a0a8b167e5145089348a368e9bdc283@battelle.org> Message-ID: <8458811f-bbdb-d024-01f5-b2ceb9fe91a5@tompassin.net> Glad there has been progress! What do you mean when you write "Python not recognizing the script calls"? I can think of several meanings, and there are probably more that haven't occurred to me: 1. The plugin doesn't import; 2. The plugin imports but you can't actually use the imported classes and functions; 3. You are trying to run a ChemPlugin Python program (outside of Python) but it can't be found; 4. You are trying to run a ChemPlugin batch file (outside of Python) but it can't be found; 5. Your Python program is trying to run a ChemPlugin Python or batch file but that fails; On 10/18/2022 5:12 PM, Walsh, Ginny (US) wrote: > Thank you for the feedback- I think with the change in the location to my user area at least one hurdle has been overcome, I can now see ChemPlugin when I print listdir. I immediately hit the next issue of Python not recognizing the script calls, but this is my first hint of success in 3 days. > > Thanks again, I'll start troubleshooting the next obstacle now > > -----Original Message----- > From: Python-list On Behalf Of Thomas Passin > Sent: Tuesday, October 18, 2022 3:10 PM > To: python-list at python.org > Subject: Re: Apparent Issue with Administrator Privileges > > [ Message received from outside the Battelle network. Carefully examine it before you open any links or attachments ] > > Looking at the ChemPlugin site, it looks like by default it would install into "C:\Program Files". Typically ordinary users do not have full privileges there, although they may have read privileges. If this is the case, either you would need to run it in an elevated > (adminstrator) session, or try to reinstall it somewhere you do have privileges. You probably need to have write privileges too, since Python will try to write its compiled files into the same tree (but these files may have been created during installation so possibly not an issue). Re-installing it might require moving the license as well. > > Note that I have never used this product, so I don't have any personal experience about it to call on. > > On 10/18/2022 2:19 PM, Walsh, Ginny (US) wrote: >> Hello- >> >> I've been struggling with resolving environmental variables issues and I believe it is linked to my company's administrator privileges. The program is called ChemPlugin and I am attempting to run it using Python 3.10.8 on Windows. I can't seem to get Python to recognize the PYTHONPATH that points to the ChemPlugin\src. I have to download ChemPlugin using my administrator login name, but Python is loaded to my local user profile. I can't seem to bridge the gap. >> >> I have been working with both the ChemPlugin group and our internal IT and we are all stumped. Is there any experience with this issue? >> >> Thanks, >> >> Ginny > > -- > https://urldefense.us/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!KDPClUfJviaPOhR6OKx54WEM!PvDHZt2yzFoHwoii4ZobbVMYqZSCyKpT92uwP3ZIbVHf0LB5pttKbQw4QmRTJVvQ$ From hjp-python at hjp.at Tue Oct 18 20:59:42 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Wed, 19 Oct 2022 02:59:42 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> Message-ID: <20221019005942.dfnzyukafmibr56c@hjp.at> On 2022-10-17 09:25:00 +0200, Karsten Hilbert wrote: > > which had special combinations for all the BASIC keywords). And if you > > go this way, why not go a step further and dissociate the program from > > its linear text representation? Add footnotes, different views, > > hyperlinks, format mathematical expressions like formulas, etc. > > http://literateprogramming.com/ Right. That's one of the inspirations for my comment. But literate programming is of course still very much rooted in the "linear text representation" paradigm. You have one definite source which is a linear text. In a world of IDEs, databases and hypertext that's probably not the best we can do. As Raymond Hettinger would say, "there must be a better way". It would be very different from mainstream programming languages, however. And ideally you would want it to integrate with a lot of other infrastructure. So that alone might make it a non-starter, even if it was really good (which realistically early iterations wouldn't be). hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From rosuav at gmail.com Tue Oct 18 21:10:52 2022 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 19 Oct 2022 12:10:52 +1100 Subject: for -- else: what was the motivation? In-Reply-To: <20221019005942.dfnzyukafmibr56c@hjp.at> References: <433a0cd3-48b1-6aae-7bd0-f13828002947@declassed.art> <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> <20221019005942.dfnzyukafmibr56c@hjp.at> Message-ID: On Wed, 19 Oct 2022 at 12:01, Peter J. Holzer wrote: > > On 2022-10-17 09:25:00 +0200, Karsten Hilbert wrote: > > > which had special combinations for all the BASIC keywords). And if you > > > go this way, why not go a step further and dissociate the program from > > > its linear text representation? Add footnotes, different views, > > > hyperlinks, format mathematical expressions like formulas, etc. > > > > http://literateprogramming.com/ > > Right. That's one of the inspirations for my comment. > > But literate programming is of course still very much rooted in the > "linear text representation" paradigm. You have one definite source > which is a linear text. > > In a world of IDEs, databases and hypertext that's probably not the best > we can do. As Raymond Hettinger would say, "there must be a better way". > > It would be very different from mainstream programming languages, > however. And ideally you would want it to integrate with a lot of other > infrastructure. So that alone might make it a non-starter, even if it > was really good (which realistically early iterations wouldn't be). > There are special-purpose languages like Scratch which are not simple text in that form. My Twitch channel bot has a command executor whose language, if you call it that, is basically JSON - and the way to edit those commands is very Scratch-inspired. These are not general-purpose programming languages, but for what they do, they can be very useful. It's a great way to put together incredibly high level primitives that tie in well with the system they're in. (Imagine programming a model train set, with primitives like "change the points here to go straight" and "advance train #32 to the next red signal".) I'm not sure how you'd make that useful for general-purpose programming, but there's definitely a LOT of value in non-textual languages for certain situations. ChrisA From sjeik_appie at hotmail.com Wed Oct 19 07:02:55 2022 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Wed, 19 Oct 2022 13:02:55 +0200 Subject: Yaml.unsafe_load error Message-ID: Hi, I am trying to create a celery.schedules.crontab object from an external yaml file. I can successfully create an instance from a dummy class "Bar", but the crontab class seems call __setstate__ prior to __init__. I have no idea how to solve this. Any ideas? See code below. Thanks! Albert-Jan Python 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import yaml >>> from celery.schedules import crontab >>> crontab(hour=3, minute=0) >>> yaml.unsafe_load('!!python/name:celery.schedules.crontab') >>> yaml.safe_load('celery.schedules.crontab:\n?? hour: 3\n?? minute: 0\n') {'celery.schedules.crontab': {'hour': 3, 'minute': 0}} >>> class Bar: ...???? def __init__(self, x, y): ...???????? pass ... >>> bar = yaml.unsafe_load('!!python/object:__main__.Bar\n?? x: 42\n?? y: 666') >>> bar <__main__.Bar object at 0x7f43b464bb38> >>> bar.x 42 ? # what is the correct way for the next line? >>> yaml.unsafe_load('!!python/object:celery.schedules.crontab\n?? hour: 3\n?? minute: 30') Traceback (most recent call last): ? File "", line 1, in ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/__init__.py", line 182, in unsafe_load ??? return load(stream, UnsafeLoader) ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/__init__.py", line 114, in load ??? return loader.get_single_data() ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/constructor.py", line 51, in get_single_data ??? return self.construct_document(node) ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/constructor.py", line 60, in construct_document ??? for dummy in generator: ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/constructor.py", line 621, in construct_python_object ??? self.set_python_instance_state(instance, state) ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/constructor.py", line 727, in set_python_instance_state ??? instance, state, unsafe=True) ? File "/home/albertjan at mycompany/envs/myenv/lib64/python3.6/site-packages/yaml/constructor.py", line 597, in set_python_instance_state ??? instance.__setstate__(state) ? File "/home/albertjan at mycompany/envs/myenv/lib/python3.6/site-packages/celery/schedules.py", line 541, in __setstate__ ??? super().__init__(**state) TypeError: __init__() got an unexpected keyword argument 'hour' From boblatest at yahoo.com Wed Oct 19 09:25:52 2022 From: boblatest at yahoo.com (Robert Latest) Date: 19 Oct 2022 13:25:52 GMT Subject: xml.etree and namespaces -- why? Message-ID: Hi all, For the impatient: Below the longish text is a fully self-contained Python example that illustrates my problem. I'm struggling to understand xml.etree's handling of namespaces. I'm trying to parse an Inkscape document which uses several namespaces. From etree's documentation: If the XML input has namespaces, tags and attributes with prefixes in the form prefix:sometag get expanded to {uri}sometag where the prefix is replaced by the full URI. Which means that given an Element e, I cannot directly access its attributes using e.get() because in order to do that I need to know the URI of the namespace. So rather than doing this (see example below): label = e.get('inkscape:label') I need to do this: label = e.get('{' + uri_inkscape_namespace + '}label') ...which is the method mentioned in etree's docs: One way to search and explore this XML example is to manually add the URI to every tag or attribute in the xpath of a find() or findall(). [...] A better way to search the namespaced XML example is to create a dictionary with your own prefixes and use those in the search functions. Good idea! Better yet, that dictionary or rather, its reverse, already exists, because etree has used it to unnecessarily mangle the namespaces in the first place. The documentation doesn't mention where it can be found, but we can just use the 'xmlns:' attributes of the root element to rebuild it. Or so I thought, until I found out that etree deletes exactly these attributes before handing the element to the user. I'm really stumped here. Apart from the fact that I think XML is bloated shit anyway and has no place outside HTML, I just don't get the purpose of etree's way of working: 1) Evaluate 'xmlns:' attributes of the element 2) Use that info to replace the existing prefixes by {uri} 3) Realizing that using {uri} prefixes is cumbersome, suggest to the user to build their own prefix -> uri dictionary to undo the effort of doing 1) and 2) 4) ...but witholding exactly the information that existed in the original document by deleting the 'xmlns:' attributes from the tag Why didn't they leave the whole damn thing alone? Keep intact and keep the attribute 'prefix:key' literally as they are. For anyone wanting to use the {uri} prefixes (why would they) they could have thrown in a helper function for the prefix->URI translation. I'm assuming that etree's designers knew what they were doing in order to make my life easier when dealing with XML. Maybe I'm missing the forest for the trees. Can anybody enlighten me? Thanks! #### self-contained example import xml.etree.ElementTree as ET def test_svg(xml): root = ET.fromstring(xml) for e in root.iter(): print(e.tag) # tags are shown prefixed with {URI} if e.tag.endswith('svg'): # Since namespaces are defined inside the tag, let's use the info # from the 'xmlns:' attributes to undo etree's URI prefixing print('Element :') for k, v in e.items(): print(' %s: %s' % (k, v)) # ...but alas: the 'xmlns:' attributes have been deleted by the parser xml = ''' ''' if __name__ == '__main__': test_svg(xml) From axy at declassed.art Wed Oct 19 11:23:56 2022 From: axy at declassed.art (Axy) Date: Wed, 19 Oct 2022 16:23:56 +0100 Subject: xml.etree and namespaces -- why? In-Reply-To: References: Message-ID: <6715508f-e13c-c3e7-98d7-4fadda4420a6@declassed.art> I mean, it's worth to look at BeautifulSoup source how do they do that. With BS I work with attributes exactly as you want, and I explicitly tell BS to use lxml parser. Axy. On 19/10/2022 14:25, Robert Latest via Python-list wrote: > Hi all, > > For the impatient: Below the longish text is a fully self-contained Python > example that illustrates my problem. > > I'm struggling to understand xml.etree's handling of namespaces. I'm trying to > parse an Inkscape document which uses several namespaces. From etree's > documentation: > > If the XML input has namespaces, tags and attributes with prefixes in the > form prefix:sometag get expanded to {uri}sometag where the prefix is > replaced by the full URI. > > Which means that given an Element e, I cannot directly access its attributes > using e.get() because in order to do that I need to know the URI of the > namespace. So rather than doing this (see example below): > > label = e.get('inkscape:label') > > I need to do this: > > label = e.get('{' + uri_inkscape_namespace + '}label') > > ...which is the method mentioned in etree's docs: > > One way to search and explore this XML example is to manually add the URI > to every tag or attribute in the xpath of a find() or findall(). > [...] > A better way to search the namespaced XML example is to create a > dictionary with your own prefixes and use those in the search functions. > > Good idea! Better yet, that dictionary or rather, its reverse, already exists, > because etree has used it to unnecessarily mangle the namespaces in the first > place. The documentation doesn't mention where it can be found, but we can > just use the 'xmlns:' attributes of the root element to rebuild it. Or > so I thought, until I found out that etree deletes exactly these attributes > before handing the element to the user. > > I'm really stumped here. Apart from the fact that I think XML is bloated shit > anyway and has no place outside HTML, I just don't get the purpose of etree's > way of working: > > 1) Evaluate 'xmlns:' attributes of the element > 2) Use that info to replace the existing prefixes by {uri} > 3) Realizing that using {uri} prefixes is cumbersome, suggest to > the user to build their own prefix -> uri dictionary > to undo the effort of doing 1) and 2) > 4) ...but witholding exactly the information that existed in the original > document by deleting the 'xmlns:' attributes from the tag > > Why didn't they leave the whole damn thing alone? Keep intact and keep > the attribute 'prefix:key' literally as they are. For anyone wanting to use > the {uri} prefixes (why would they) they could have thrown in a helper > function for the prefix->URI translation. > > I'm assuming that etree's designers knew what they were doing in order to make > my life easier when dealing with XML. Maybe I'm missing the forest for the > trees. Can anybody enlighten me? Thanks! > > > #### self-contained example > import xml.etree.ElementTree as ET > > def test_svg(xml): > root = ET.fromstring(xml) > for e in root.iter(): > print(e.tag) # tags are shown prefixed with {URI} > if e.tag.endswith('svg'): > # Since namespaces are defined inside the tag, let's use the info > # from the 'xmlns:' attributes to undo etree's URI prefixing > print('Element :') > for k, v in e.items(): > print(' %s: %s' % (k, v)) > # ...but alas: the 'xmlns:' attributes have been deleted by the parser > > xml = ''' > > > width="210mm" > height="297mm" > viewBox="0 0 210 297" > version="1.1" > id="svg285" > inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" > sodipodi:docname="test.svg" > xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" > xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" > xmlns="http://www.w3.org/2000/svg" > xmlns:svg="http://www.w3.org/2000/svg"> > id="namedview287" > pagecolor="#ffffff" > bordercolor="#000000" > borderopacity="0.25" > inkscape:showpageshadow="2" > inkscape:pageopacity="0.0" > inkscape:pagecheckerboard="0" > inkscape:deskcolor="#d1d1d1" > inkscape:document-units="mm" > showgrid="false" > inkscape:zoom="0.2102413" > inkscape:cx="394.78447" > inkscape:cy="561.25984" > inkscape:window-width="1827" > inkscape:window-height="1177" > inkscape:window-x="85" > inkscape:window-y="-8" > inkscape:window-maximized="1" > inkscape:current-layer="layer1" /> > id="defs282" /> > inkscape:label="Ebene 1" > inkscape:groupmode="layer" > id="layer1"> > style="fill:#aaccff;stroke-width:0.264583" > id="rect289" > width="61.665253" > height="54.114403" > x="33.978813" > y="94.38559" /> > > > ''' > > if __name__ == '__main__': > test_svg(xml) From axy at declassed.art Wed Oct 19 10:53:37 2022 From: axy at declassed.art (Axy) Date: Wed, 19 Oct 2022 15:53:37 +0100 Subject: xml.etree and namespaces -- why? In-Reply-To: References: Message-ID: <61117d6a-594b-f8a5-816c-daa099382072@declassed.art> I have no idea why, I used to remove namespaces, following the advice from stackoverflow: https://stackoverflow.com/questions/4255277/lxml-etree-xmlparser-remove-unwanted-namespace _ns_removal_xslt_transform = etree.XSLT(etree.fromstring(''' ??? ??? ??? ??????? ????????? ??????? ??? ??? ??????? ????????? ??????? ??? ??? ??????? ????????? ??????? ??? ??? ''')) xml_doc = _ns_removal_xslt_transform( ??? etree.fromstring(my_xml_data) ) Later on, when I worked with SVG, I used BeautifulSoup. Axy. From jon+usenet at unequivocal.eu Wed Oct 19 12:15:24 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Wed, 19 Oct 2022 16:15:24 -0000 (UTC) Subject: xml.etree and namespaces -- why? References: Message-ID: On 2022-10-19, Robert Latest wrote: > If the XML input has namespaces, tags and attributes with prefixes > in the form prefix:sometag get expanded to {uri}sometag where the > prefix is replaced by the full URI. > > Which means that given an Element e, I cannot directly access its attributes > using e.get() because in order to do that I need to know the URI of the > namespace. That's because you *always* need to know the URI of the namespace, because that's its only meaningful identifier. If you assume that a particular namespace always uses the same prefix then your code will be completely broken. The following two pieces of XML should be understood identically: and: So you can see why e.get('inkscape:label') cannot possibly work, and why e.get('{http://www.inkscape.org/namespaces/inkscape}label') makes sense. The xml.etree author obviously knew that this was cumbersome, and hence you can do something like: namespaces = {'inkspace': 'http://www.inkscape.org/namespaces/inkscape'} element = root.find('inkspace:foo', namespaces) which will work for both of the above pieces of XML. But unfortunately as far as I can see nobody's thought about doing the same for attributes rather than tags. From sjeik_appie at hotmail.com Wed Oct 19 14:01:03 2022 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Wed, 19 Oct 2022 20:01:03 +0200 Subject: Yaml.unsafe_load error In-Reply-To: Message-ID: On Oct 19, 2022 13:02, Albert-Jan Roskam wrote: ?? Hi, ?? I am trying to create a celery.schedules.crontab object from an external ?? yaml file. I can successfully create an instance from a dummy class "Bar", ?? but the crontab class seems call __setstate__ prior to __init__. I have no ?? idea how to solve this. Any ideas? See code below. ?? Thanks! ?? Albert-Jan ? ? ?? ? ?? # what is the correct way for the next line? ?? >>> yaml.unsafe_load('!!python/object:celery.schedules.crontab\n?? hour: ?? 3\n?? minute: 30') ?? ==== Reading the source a bit more, me thinks it might be: yaml.unsafe_load('!!python/object/apply:celery.schedules.crontab\nkwds:\n? ?hour: 3\n? ?minute: 30') I did not yet test this, though. From boblatest at yahoo.com Wed Oct 19 13:36:06 2022 From: boblatest at yahoo.com (Robert Latest) Date: 19 Oct 2022 17:36:06 GMT Subject: xml.etree and namespaces -- why? References: Message-ID: Jon Ribbens wrote: > That's because you *always* need to know the URI of the namespace, > because that's its only meaningful identifier. If you assume that a > particular namespace always uses the same prefix then your code will be > completely broken. The following two pieces of XML should be understood > identically: > > > > > and: > > > > > So you can see why e.get('inkscape:label') cannot possibly work, and why > e.get('{http://www.inkscape.org/namespaces/inkscape}label') makes sense. I get it. It does. > The xml.etree author obviously knew that this was cumbersome, and > hence you can do something like: > > namespaces = {'inkspace': 'http://www.inkscape.org/namespaces/inkscape'} > element = root.find('inkspace:foo', namespaces) > > which will work for both of the above pieces of XML. Makes sense. It forces me to make up my own prefixes which I can then safely use in my code rather than relying on the xml's generator to not change their prefixes. BTW, I only now thought to look at what actually is at Inkscape's namespace URI, and it turns out to be quite a nice explanation of what a namespace is and why it looks like a URL. From wallacechemical at gmail.com Thu Oct 20 06:01:59 2022 From: wallacechemical at gmail.com (wdamn) Date: Thu, 20 Oct 2022 03:01:59 -0700 (PDT) Subject: Portable executable on OSX Message-ID: hi all, I would like to have a portable executable of python3 on OSX. I google a lot about it, but I could not find any solution. Am I missing something or is it simply not possible? thanks From cs at cskk.id.au Thu Oct 20 16:53:45 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Fri, 21 Oct 2022 07:53:45 +1100 Subject: Portable executable on OSX In-Reply-To: References: Message-ID: On 20Oct2022 03:01, wdamn wrote: >I would like to have a portable executable of python3 on OSX. > >I google a lot about it, but I could not find any solution. >Am I missing something or is it simply not possible? I'm not sure what you mean. My Mac comes presupplied with Python 3, and I'd expect any modern Mac to be the same. So a python 3 programme should work on any Mac. If you mean: "how do I write a Python script to use python 3?" the usual approach is to start the script with a shebang line like this: #!/usr/bin/env python3 On _any_ UNIX or UNIXlike system (OSX/MacOS is a BSD derived UNIX) this will run the script with your usual "python3" command if you invoke the script as a command. Cheers, Cameron Simpson From list1 at tompassin.net Thu Oct 20 17:48:34 2022 From: list1 at tompassin.net (Thomas Passin) Date: Thu, 20 Oct 2022 17:48:34 -0400 Subject: Portable executable on OSX In-Reply-To: References: Message-ID: "Portable executable" usually means that the program resides on removable media, like a USB stick. You can go to a computer, plug the stick in, and run the program. If it's Python, then the installation on the removable medium needs to set up all the paths and directories correctly before actually running Python. That would typically be done with batch files setting paths and environmental variables. I got this working for Python on Windows some years ago. Here is the setup batch file I used - it gets executed when the user types "pyth37": @echo off setlocal : Find effective drive for this file. set ed=%~d0 path %ed%\python37\Scripts;%ed%\python37;%PATH% set PYTHONUSERBASE=%ed%\user\python set HOME=%ed%\user\python call python %* endlocal It might need to be be more complex on MacOS, but it gives you the idea. The odd-looking line "set ed=%~d0" is a Windows-specific way to get the drive of the command file being run. On 10/20/2022 4:53 PM, Cameron Simpson wrote: > On 20Oct2022 03:01, wdamn wrote: >> I would like to have a portable executable of python3 on OSX. >> >> I google a lot about it, but I could not find any solution. >> Am I missing something or is it simply not possible? > > I'm not sure what you mean. My Mac comes presupplied with Python 3, and > I'd expect any modern Mac to be the same. So a python 3 programme should > work on any Mac. > > If you mean: "how do I write a Python script to use python 3?" the usual > approach is to start the script with a shebang line like this: > > ??? #!/usr/bin/env python3 > > On _any_ UNIX or UNIXlike system (OSX/MacOS is a BSD derived UNIX) this > will run the script with your usual "python3" command if you invoke the > script as a command. > > Cheers, > Cameron Simpson From rosuav at gmail.com Thu Oct 20 17:53:51 2022 From: rosuav at gmail.com (Chris Angelico) Date: Fri, 21 Oct 2022 08:53:51 +1100 Subject: Portable executable on OSX In-Reply-To: References: Message-ID: On Fri, 21 Oct 2022 at 08:50, Thomas Passin wrote: > > "Portable executable" usually means that the program resides on > removable media, like a USB stick. You can go to a computer, plug the > stick in, and run the program. If it's Python, then the installation on > the removable medium needs to set up all the paths and directories > correctly before actually running Python. That would typically be done > with batch files setting paths and environmental variables. > > I got this working for Python on Windows some years ago. Here is the > setup batch file I used - it gets executed when the user types "pyth37": > > @echo off > setlocal > : Find effective drive for this file. > set ed=%~d0 > path %ed%\python37\Scripts;%ed%\python37;%PATH% > set PYTHONUSERBASE=%ed%\user\python > set HOME=%ed%\user\python > call python %* > endlocal > > It might need to be be more complex on MacOS, but it gives you the idea. > The odd-looking line "set ed=%~d0" is a Windows-specific way to get > the drive of the command file being run. > Basic idea looks sound. Might actually be _easier_ on OSX, since it's Unix-like and you should be able to depend on /bin/bash. The notation `dirname $0` should give you the path to the current script, from which everything else can be calculated. (Caveat: Never actually done this on a Mac, and only did cursory web searching to check that it wasn't a ridiculous idea.) ChrisA From PythonList at DancesWithMice.info Fri Oct 21 00:40:57 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 21 Oct 2022 17:40:57 +1300 Subject: Third round of the Smart Iterator Challenge: September-October 2022 Message-ID: <617bbff9-a5c8-cc3f-bfda-fa2708bdd66f@DancesWithMice.info> Challenge-week 3: Generalising the solution, starts today! Details from the Meetup site: https://www.meetup.com/nzpug-auckland/events/288813734/ A virtual event run by the Auckland Branch of the New Zealand Python Users' Group. It's Week 3 of the Smart Iterator Challenge! Time to see how modules and namespaces provide building-blocks which enable us to cope with change. Can you anticipate and manage change? The tutorial demonstrates SOLID's SRP (and a bit of OCP) for those who want to learn more than Python-coding. This Challenge will interest Python-Journeymen, and Python-Apprentices ready to move-on from ?the basics?. There is a separate-but-related question for Python-Masters and any advanced Journeymen who are finding the main Challenge too-easy (available upon personal request), in recognition of being prepared to help others. We start with a review of Challenge-week 2 and a sample-answer to download and compare with your own efforts. Challenge-week 3 starts with either your own or a provided template-script, so you don't have to have completed Challenge-weeks 1 and 2 (but it will help). Again, there is a tutorial in case you haven't met namespaces before. Followed by multiple specifications to implement. In many ways, the challenge is not so much writing code, as it is designing a code-solution. Putting code-modules together, something like a jig-saw puzzle! Challenge Schedule: Generalising the solution Starting: Sat 22 Oct Office Hours: 1830*, Wed 26 Oct Concluding: midnight after Sun 30 Oct * all times NZDT (UTC+13) Are you up for a challenge? Regards =dn (for Pete and DJ) From boblatest at yahoo.com Fri Oct 21 08:34:16 2022 From: boblatest at yahoo.com (Robert Latest) Date: 21 Oct 2022 12:34:16 GMT Subject: Need help with custom string formatter Message-ID: Hi all, I would like to modify the standard str.format() in a way that when the input field is of type str, there is some character replacement, and the string gets padded or truncated to the given field width. Basically like this: fmt = MagicString('<{s:6}>') print(fmt.format(s='?u?erst')) Output: I've written a function fix_format() which, given a string and a field width, does just that. However, I find myself unable to implement a Formatter that uses this function in the intened way. See the example below, I hope I sprinkled it with enough comments to make my intents clear. Thanks for any enlightenment. The interesting part starts somewhere in the middle. ### Self contained example import re from string import Formatter _replacements = [(re.compile(rx), repl) for rx, repl in (\ ('?', 'Ae'), ('?', 'ae'), ('?', 'Oe'), ('?', 'oe'), ('?', 'Ue'), ('?', 'ue'), ('?', 'ss'))] def fix_format(text, width): # Seven regex passes seems awfully inefficient. I can't think of a # better way. Besides the point though. for rx, repl in _replacements: text = re.sub(rx, repl, text) # return truncated / padded version of string return text[:width] + ' ' * max(0, width - len(text)) class Obj(): """I'm just an object with some attributes""" def __init__(self, **kw): self.__dict__.update(kw) o = Obj(x="I am X, and I'm too long", y="??? Ich bin auch zu lang") z = 'Pad me!' format_spec = '<{o.x:6}>\n<{o.y:6}>\n<{z:10}>' # Standard string formatting print('Standard string formatting:') print(format_spec.format(o=o, z=z)) # Demonstrate fix_format() print('\nWanted output:') print('<' + fix_format(o.x, 6) + '>') print('<' + fix_format(o.y, 6) + '>') print('<' + fix_format(z, 10) + '>') ##### This is where my struggle begins. ##### class MagicString(Formatter): def __init__(self, format_spec): self.spec = format_spec super().__init__() def format(self, **kw): return(self.vformat(self.spec, [], kw)) def get_field(self, name, a, kw): # Compound fields have a dot: obj_name, _, key = name.partition('.') obj = getattr(kw[obj_name], key) if key else kw[obj_name] if isinstance(obj, str): # Here I would like to call fix_format(), but I don't know where # to get the field width. print('get_field(): <' + obj + '>') else: # Here I'd like to use the "native" formatter of whatever type # the field is. pass return obj, key def get_value(self, key, a, kw): '''I don't understand what this method is for, it never gets called''' raise NotImplementedError fmt = MagicString(format_spec) print('\nReal output:') print(fmt.format(o=o, z=z)) # Weirdly, somewhere on the way the standard formatting kicks in, too, as # the 'Pad me!' string does get padded (which must be some postprocessing, # as the string is still unpadded when passed into get_field()) From boblatest at yahoo.com Fri Oct 21 12:06:32 2022 From: boblatest at yahoo.com (Robert Latest) Date: 21 Oct 2022 16:06:32 GMT Subject: Need help with custom string formatter References: Message-ID: Stefan Ram wrote: [the solution] thanks, right on the spot. I had already figured out that format_field() is the one method I need, and thanks for the str.translate method. I knew that raking seven RE's across the same string HAD to be stupid. Have a nice weekend! From boblatest at yahoo.com Fri Oct 21 12:37:23 2022 From: boblatest at yahoo.com (Robert Latest) Date: 21 Oct 2022 16:37:23 GMT Subject: Need help with custom string formatter References: Message-ID: Hi Stefan, I have now implemented a version of this, works nicely. I have a few minor questions / remarks: > result += ' ' *( length - len( result )) Nice, I didn't know that one could multiply strings by negative numbers without error. > def __init__( self ): > super().__init__() Isn't this a no-op? Probably a leftover from my stuff. > def format_field( self, value, format_string ): > if re.match( r'\d+', format_string )and type( value )== str: Why do you prefer re.match(r'\d+', x) over x.isdigit()? > return super().format_field( value, format_string ) Why do you prefer super().format_field() over plain format()? The doc says: "format_field() simply calls format()." So I figured I might do the same. Thanks! From cs at cskk.id.au Fri Oct 21 19:04:18 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Sat, 22 Oct 2022 10:04:18 +1100 Subject: Need help with custom string formatter In-Reply-To: References: Message-ID: On 21Oct2022 16:55, Stefan Ram wrote: >Robert Latest writes: >>>return super().format_field( value, format_string ) >>Why do you prefer super().format_field() over plain format()? The doc says: >>"format_field() simply calls format()." So I figured I might do the same. > > I am not aware of any reason not to call "format" directly. Stefan's code implements it's own format_field and falls back to the original format_field(). That's standard subclassing practice, and worth doing reflexively more of the time - it avoids _knowing_ that format_field() just calls format(). So I'd take Stefan's statement above to imply that calling format() directly should work. My own habit would be to stick with the original, if only for semantic reasons. Supposing you switched from subclassing Formatter to some other class which itself subclasses Formatter. (Yes, that is probably something you will never do.) Bypassing the call to super().format_field(...) prevents shoehorning some custom format_fields from the changed superclass. Which you'd then need to debug. That's all. Cheers, Cameron Simpson From cs at cskk.id.au Fri Oct 21 19:05:11 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Sat, 22 Oct 2022 10:05:11 +1100 Subject: Need help with custom string formatter In-Reply-To: References: Message-ID: On 21Oct2022 16:55, Stefan Ram wrote: > I was not aware of "isdigit". There's also "isdecimal" and "isnumeric". They all have subtly different meanings :-) Cheers, Cameron Simpson From hjp-python at hjp.at Sat Oct 22 09:04:58 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sat, 22 Oct 2022 15:04:58 +0200 Subject: for -- else: what was the motivation? In-Reply-To: References: <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> <20221019005942.dfnzyukafmibr56c@hjp.at> Message-ID: <20221022130458.4svttadgdui2w72q@hjp.at> On 2022-10-19 12:10:52 +1100, Chris Angelico wrote: > On Wed, 19 Oct 2022 at 12:01, Peter J. Holzer wrote: > > On 2022-10-17 09:25:00 +0200, Karsten Hilbert wrote: > > > http://literateprogramming.com/ > > > > Right. That's one of the inspirations for my comment. > > > > But literate programming is of course still very much rooted in the > > "linear text representation" paradigm. You have one definite source > > which is a linear text. > > > > In a world of IDEs, databases and hypertext that's probably not the best > > we can do. As Raymond Hettinger would say, "there must be a better way". > > > > It would be very different from mainstream programming languages, > > however. And ideally you would want it to integrate with a lot of other > > infrastructure. So that alone might make it a non-starter, even if it > > was really good (which realistically early iterations wouldn't be). > > There are special-purpose languages like Scratch which are not simple > text in that form. Yes, I know. It has a different goal though: Scratch tries to establish a friendly learning environment. Get rid of typing and syntax errors that beginners find so frustrating. What I'm interested in is an enviroment for developing medium-sized real applications. Somewhere in the several person-months to several person-years of effort, hundreds of user-stories, maybe thousands of bug-reports and change-requests over its life-time. The people using such a system/language would be professional programmers. They probably don't need much help to get the syntax of a for loop right. What they do need, though: * Cross-reference between requirements and code. (Yes, you can write comments, yes, you will hopefully have meaningful commit messages. Still, I see a lot of room for improvements there) * Cross-references between related parts of the code. (Yes, many IDEs can jump to the definition of an instance or list all instances of a definiton, But sometimes the relationship isn't that mechanic. And yes, you can use comments fpr that, too) * Views which highlight some parts of the code and omit others. (Folding editors do that in a very limited fashion) * For example, I might want to see only the code proper when I'm focusing on an algorithm or I might want to see lots of context (type definitions, requirements, test results, ...) * Classes often have quite a lot of methods with no natural order. Being able to view only a subset of them in some custom order may help. * Going back to the core idea of literate programming: Especially views which show some requirement(s) together with the code that implements them plus some explanation why that implementation was chosen. Presented like this, it's clear that the "language" (i.e. the file format) is probably the smallest part of the problem. How the user can view the program, how they can edit it, and how to keep the whole thing manageable is a much bigger question. And it would probably be a good idea to start at the system level and not at the language level. > My Twitch channel bot has a command executor whose language, if you > call it that, is basically JSON - and the way to edit those commands > is very Scratch-inspired. I designed a graphical filter language for database queries once. The idea was that you could combine various operations (selects, projections, grouping, transformations, ...) into pipelines via a web interface. We did implement it (sadly it wasn't me who did it), and it turned out to be a lot harder than I thought to make that actually usable. And of course there have been lots of CASE tools over the years. That seems to have been mostly a fad of 90s. Still, there were some good ideas there (although not alway implemented well), and something bubbles back up every now and then. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From hjp-python at hjp.at Sat Oct 22 09:14:33 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sat, 22 Oct 2022 15:14:33 +0200 Subject: for -- else: what was the motivation? In-Reply-To: <20221022130458.4svttadgdui2w72q@hjp.at> References: <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> <20221019005942.dfnzyukafmibr56c@hjp.at> <20221022130458.4svttadgdui2w72q@hjp.at> Message-ID: <20221022131433.dnjx4vi4qojlvfil@hjp.at> On 2022-10-22 15:04:58 +0200, Peter J. Holzer wrote: > On 2022-10-19 12:10:52 +1100, Chris Angelico wrote: > > On Wed, 19 Oct 2022 at 12:01, Peter J. Holzer wrote: > > > On 2022-10-17 09:25:00 +0200, Karsten Hilbert wrote: > > > > http://literateprogramming.com/ > > > > > > Right. That's one of the inspirations for my comment. > > > > > > But literate programming is of course still very much rooted in the > > > "linear text representation" paradigm. You have one definite source > > > which is a linear text. > > > > > > In a world of IDEs, databases and hypertext that's probably not the best > > > we can do. As Raymond Hettinger would say, "there must be a better way". > > > > > > It would be very different from mainstream programming languages, > > > however. And ideally you would want it to integrate with a lot of other > > > infrastructure. So that alone might make it a non-starter, even if it > > > was really good (which realistically early iterations wouldn't be). > > > > There are special-purpose languages like Scratch which are not simple > > text in that form. > > Yes, I know. > > It has a different goal though: Scratch tries to establish a friendly > learning environment. Get rid of typing and syntax errors that beginners > find so frustrating. > > What I'm interested in is an enviroment for developing medium-sized real > applications. Somewhere in the several person-months to several > person-years of effort, hundreds of user-stories, maybe thousands of > bug-reports and change-requests over its life-time. [...] > And of course there have been lots of CASE tools over the years. A possibly totally different approach: There are tools[1] for authors which are supposed to help them keep all their characters, events, timelines, etc. in order. I have never used one (I don't plan to write a novel anytime soon), but what I've heard of them sounds like it would be useful for software-development, too. hp [1] E.g. Campfire (https://www.campfirewriting.com/) -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: From drewmossedyou1 at gmail.com Sat Oct 22 11:32:10 2022 From: drewmossedyou1 at gmail.com (Drew Pierson) Date: Sat, 22 Oct 2022 11:32:10 -0400 Subject: for -- else: what was the motivation? In-Reply-To: <20221022130458.4svttadgdui2w72q@hjp.at> References: <9db5003a-b38d-51d7-1eae-389adaac394f@btinternet.com> <004e01d8e0e8$7d9ec020$78dc4060$@gmail.com> <0265365a-39bb-f40e-f0b1-31943b74f924@vub.be> <20221016170103.htj57q43ux5lqzy5@hjp.at> <20221019005942.dfnzyukafmibr56c@hjp.at> <20221022130458.4svttadgdui2w72q@hjp.at> Message-ID: the fuck? On Sat, Oct 22, 2022 at 9:06 AM Peter J. Holzer wrote: > On 2022-10-19 12:10:52 +1100, Chris Angelico wrote: > > On Wed, 19 Oct 2022 at 12:01, Peter J. Holzer wrote: > > > On 2022-10-17 09:25:00 +0200, Karsten Hilbert wrote: > > > > http://literateprogramming.com/ > > > > > > Right. That's one of the inspirations for my comment. > > > > > > But literate programming is of course still very much rooted in the > > > "linear text representation" paradigm. You have one definite source > > > which is a linear text. > > > > > > In a world of IDEs, databases and hypertext that's probably not the > best > > > we can do. As Raymond Hettinger would say, "there must be a better > way". > > > > > > It would be very different from mainstream programming languages, > > > however. And ideally you would want it to integrate with a lot of other > > > infrastructure. So that alone might make it a non-starter, even if it > > > was really good (which realistically early iterations wouldn't be). > > > > There are special-purpose languages like Scratch which are not simple > > text in that form. > > Yes, I know. > > It has a different goal though: Scratch tries to establish a friendly > learning environment. Get rid of typing and syntax errors that beginners > find so frustrating. > > What I'm interested in is an enviroment for developing medium-sized real > applications. Somewhere in the several person-months to several > person-years of effort, hundreds of user-stories, maybe thousands of > bug-reports and change-requests over its life-time. > > The people using such a system/language would be professional > programmers. They probably don't need much help to get the syntax of a > for loop right. What they do need, though: > > * Cross-reference between requirements and code. (Yes, you can write > comments, yes, you will hopefully have meaningful commit messages. > Still, I see a lot of room for improvements there) > * Cross-references between related parts of the code. (Yes, many IDEs > can jump to the definition of an instance or list all instances of a > definiton, But sometimes the relationship isn't that mechanic. And > yes, you can use comments fpr that, too) > * Views which highlight some parts of the code and omit others. (Folding > editors do that in a very limited fashion) > * For example, I might want to see only the code proper when I'm > focusing on an algorithm or I might want to see lots of context > (type definitions, requirements, test results, ...) > * Classes often have quite a lot of methods with no natural order. > Being able to view only a subset of them in some custom order may > help. > * Going back to the core idea of literate programming: Especially > views which show some requirement(s) together with the code that > implements them plus some explanation why that implementation was > chosen. > > Presented like this, it's clear that the "language" (i.e. the file > format) is probably the smallest part of the problem. How the user can > view the program, how they can edit it, and how to keep the whole thing > manageable is a much bigger question. And it would probably be a good > idea to start at the system level and not at the language level. > > > > My Twitch channel bot has a command executor whose language, if you > > call it that, is basically JSON - and the way to edit those commands > > is very Scratch-inspired. > > I designed a graphical filter language for database queries once. The idea > was that you could combine various operations (selects, projections, > grouping, transformations, ...) into pipelines via a web interface. We > did implement it (sadly it wasn't me who did it), and it turned out to > be a lot harder than I thought to make that actually usable. > > And of course there have been lots of CASE tools over the years. That > seems to have been mostly a fad of 90s. Still, there were some good > ideas there (although not alway implemented well), and something bubbles > back up every now and then. > > hp > > -- > _ | Peter J. Holzer | Story must make more sense than reality. > |_|_) | | > | | | hjp at hjp.at | -- Charles Stross, "Creative writing > __/ | http://www.hjp.at/ | challenge!" > -- > https://mail.python.org/mailman/listinfo/python-list > From ishar20222010 at gmail.com Fri Oct 21 23:43:43 2022 From: ishar20222010 at gmail.com (ishar jaiswal) Date: Sat, 22 Oct 2022 09:13:43 +0530 Subject: error Message-ID: my problem is not solving i sended you a message when i open python there one error comes. then you why not taking action [image: Screenshot (2).png] From boblatest at yahoo.com Sat Oct 22 10:10:49 2022 From: boblatest at yahoo.com (Robert Latest) Date: 22 Oct 2022 14:10:49 GMT Subject: Need help with custom string formatter References: Message-ID: Cameron Simpson wrote: > Stefan's code implements it's own format_field and falls back to the > original format_field(). That's standard subclassing practice, and worth > doing reflexively more of the time - it avoids _knowing_ that > format_field() just calls format(). > > So I'd take Stefan's statement above to imply that calling format() > directly should work. Yup, makes sense. From python at mrabarnett.plus.com Sat Oct 22 12:47:19 2022 From: python at mrabarnett.plus.com (MRAB) Date: Sat, 22 Oct 2022 17:47:19 +0100 Subject: error In-Reply-To: References: Message-ID: On 2022-10-22 04:43, ishar jaiswal wrote: > my problem is not solving i sended you a message when i open python there > one error comes. then you why not taking action > [image: Screenshot (2).png] This list does not accept screenshots. Please copy and paste the error. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sat Oct 22 16:58:09 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sat, 22 Oct 2022 21:58:09 +0100 Subject: A trivial question that I don't know - document a function/method Message-ID: Hi all! What is the correct way, if any, of documenting a function/method? 1. def foo(a,b): """ A description. a: Whatever 1 b: Whatever 2 """ ... 2. def foo(a,b): """ A description. a -- Whatever 1 b -- Whatever 2 """ ... 3. def foo(a,b): """ A description. @param a: Whatever 1 @param b: Whatever 2 """ ... 4. def foo(a,b): """ A description. :param a: Whatever 1 :param b: Whatever 2 """ ... 5. Any other ... Any comments/suggestions are welcome. Thanks. Paulo From drsalists at gmail.com Sat Oct 22 19:09:11 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Sat, 22 Oct 2022 16:09:11 -0700 Subject: A trivial question that I don't know - document a function/method In-Reply-To: References: Message-ID: I don't think there is a "correct" way. It depends somewhat on what tools you're using. I like pydocstyle, which I have hung off of vim with syntastic. pydocstyle checks for https://peps.python.org/pep-0257/ conformance. Also, rather than describe the types of formal parameters to functions in a docstring, I like to use mypy for https://peps.python.org/pep-0484/ with its --disallow-untyped-calls and --ignore-missing-imports options, which I hang off of a Makefile, called by a vim macro. On Sat, Oct 22, 2022 at 3:39 PM Paulo da Silva < p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > Hi all! > > What is the correct way, if any, of documenting a function/method? > > 1. > def foo(a,b): > """ A description. > a: Whatever 1 > b: Whatever 2 > """ > ... > > 2. > def foo(a,b): > """ A description. > a -- Whatever 1 > b -- Whatever 2 > """ > ... > > 3. > def foo(a,b): > """ A description. > @param a: Whatever 1 > @param b: Whatever 2 > """ > ... > > 4. > def foo(a,b): > """ A description. > :param a: Whatever 1 > :param b: Whatever 2 > """ > ... > > 5. > Any other ... > > Any comments/suggestions are welcome. > Thanks. > Paulo > > -- > https://mail.python.org/mailman/listinfo/python-list > From list1 at tompassin.net Sat Oct 22 21:49:55 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sat, 22 Oct 2022 21:49:55 -0400 Subject: A trivial question that I don't know - document a function/method In-Reply-To: References: Message-ID: <00d39481-3eff-a325-f01d-13e2a7e9acd2@tompassin.net> On 10/22/2022 4:58 PM, Paulo da Silva wrote: > Hi all! > > What is the correct way, if any, of documenting a function/method? > > 1. > def foo(a,b): > ????""" A description. > ????a: Whatever 1 > ????b: Whatever 2 > ????""" [snip] > 5. > ????Any other ... > > Any comments/suggestions are welcome. > Thanks. > Paulo This is not a trivial question - not because it is hard but because it is important, and more so when someone else needs to work with your code. It's surprising how easy it is to forget these details about even your own code. Here are some examples of how I like to document functions and methods, mostly based on PEP-257, Docstring Conventions (https://peps.python.org/pep-0257/) and Guido's style guide before it. def make_title_from_headline(self, p, h): """From node title, return title with over- and underline- strings. The leading symbol is chosen based on the indent level of the node. Note that might different from p.h because of, e.g., directive removal. ARGUMENTS p -- the node position whose indent level is to be used. h -- the headline string to be processed. RETURNS a string """ Key points - include all the arguments and the return. Capitals help lead the eye to the ARGUMENT and RETURNS blocks. If you use keyword arguments, add a KEYWORD ARGUMENTS section. def plot(self, stackposition=MAIN, clearFirst=True): """Plot a 2-D graph. ARGUMENTS self -- an instance of a PlotManager stackposition -- an integer denoting which data set to plot. clearFirst -- True if the previous plot should be cleared, else False. RETURNS nothing """ Key point -- if the function/method returns nothing, say so. class Dataset: '''Class to represent a 2D curve. ATTRIBUTES xdata, ydata -- sequences holding the x or y data sets. Must be the same length. May be lists or numpy ndarrays. auxDataset -- dictionary of auxiliary data sets (e.g., for holding statistical information) errorBands -- List of Datasets to hold errors orig_filename -- file path, if any, used to load data (before any transformations have been applied). xaxislabel -- label text for the X axis label yaxislabel -- label text for the Y axis label figurelabel -- label text for the graph of this data ymin -- minimum value for Y axis ymax -- maximum value for Y axis parms -- dictionary of parameters, Meant to store the current values so they can be written to a file. ''' If you have the space, these annotations could instead be placed in-line in the class's __init__() method. But it's not often there is enough space, and when they are in the docstring they will be extracted and displayed by docstring tools, which is a good thing. Sometimes it can happen that a function/method is is simple and clear that its name, and the names of the arguments, make it obvious what their meaning is. But that happens less often than you might think. - Be concise, but choose clarity over brevity; - Try to devise good, descriptive names as far as possible; - A long list of arguments probably should be ordered alphabetically, but could also be grouped, with each group ordered. Otherwise, it is useful to list the parameters in the order they appear in the function/method signature. - Be consistent in your docstrings, but remember there will be times that it makes more sense to relax the consistency. From Karsten.Hilbert at gmx.net Sun Oct 23 14:37:46 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Sun, 23 Oct 2022 20:37:46 +0200 Subject: A trivial question that I don't know - document a function/method In-Reply-To: <00d39481-3eff-a325-f01d-13e2a7e9acd2@tompassin.net> References: <00d39481-3eff-a325-f01d-13e2a7e9acd2@tompassin.net> Message-ID: Am Sat, Oct 22, 2022 at 09:49:55PM -0400 schrieb Thomas Passin: > def make_title_from_headline(self, p, h): > """From node title, return title with over- and underline- strings. ... > RETURNS > a string > """ .... > def plot(self, stackposition=MAIN, clearFirst=True): > """Plot a 2-D graph. ... > RETURNS > nothing > """ Would it not, these days, be clearer to def make_title_from_headline(self, p, h) -> str: def plot(self, stackposition=MAIN, clearFirst=True) -> None: and use RETURNS (or Returns:) only when what is returned warrants further explanation (say, as to what is returned when). Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From becon12 at hotmail.com Sun Oct 23 06:13:00 2022 From: becon12 at hotmail.com (B N) Date: Sun, 23 Oct 2022 10:13:00 +0000 Subject: Update from 3.9 to 3.10.8 and uninstall 3.9 Message-ID: I am new to python and wish to update 3.9 to3.10.8 which I have downloaded. How do I replace 3.9 with the 3.10.8 I downloaded. Kind regards JohnGee From i9shuaib1 at gmail.com Sun Oct 23 13:19:09 2022 From: i9shuaib1 at gmail.com (Shuaib Akhtar) Date: Sun, 23 Oct 2022 10:19:09 -0700 Subject: need help Message-ID: <71D7A169-0438-436F-8F4B-C9F0960DB1AE@hxcore.ol> How to fix Traceback (most recent call last): ? File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\socket.py", line 833, in create_connection ??? sock.connect(sa) TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond ? During handling of the above exception, another exception occurred: ? Traceback (most recent call last): ? File "C:\Users\i9shu\Downloads\python email bot\email bot.py", line 25, in ??? server = smtplib.SMTP('smtp.gmail.com',2525) ? File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\smtplib.py", line 255, in __init__ ??? (code, msg) = self.connect(host, port) ? File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\smtplib.py", line 341, in connect ??? self.sock = self._get_socket(host, port, self.timeout) ? File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\smtplib.py", line 312, in _get_socket ??? return socket.create_connection((host, port), timeout, ? File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\socket.py", line 833, in create_connection ??? sock.connect(sa) KeyboardInterrupt ? Process finished with exit code -1073741510 (0xC000013A: interrupted by Ctrl+C) eorr ? Sent from [1]Mail for Windows ? References Visible links 1. https://go.microsoft.com/fwlink/?LinkId=550986 From f96.heydari at gmail.com Sun Oct 23 08:11:10 2022 From: f96.heydari at gmail.com (Fatemeh Heydari) Date: Sun, 23 Oct 2022 05:11:10 -0700 (PDT) Subject: score function in linear regression model Message-ID: <0b2b86f6-2235-4996-83e3-0da69b3f3c76n@googlegroups.com> Hi every one ! Using sklearn and linear model I made a linear regression and I reached out to a function named "score". Does anyone know what does it exactly calculate? The code for this function is like this: model.score(X,Y) Thanks in advance! From pieter-l at vanoostrum.org Sun Oct 23 10:24:58 2022 From: pieter-l at vanoostrum.org (Pieter van Oostrum) Date: Sun, 23 Oct 2022 16:24:58 +0200 Subject: Are Floating Point Numbers still a Can of Worms? References: <769f670e-92b4-401e-8d9e-4b8d12a0925dn@googlegroups.com> Message-ID: Mostowski Collapse writes: > I also get: > > Python 3.11.0rc1 (main, Aug 8 2022, 11:30:54) >>>> 2.718281828459045**0.8618974796837966 > 2.367649 > > Nice try, but isn't this one the more correct? > > ?- X is 2.718281828459045**0.8618974796837966. > X = 2.3676489999999997. > That's probably the accuracy of the underlying C implementation of the exp function. In [25]: exp(0.8618974796837966) Out[25]: 2.367649 But even your answer can be improved: Maxima: (%i1) fpprec:30$ (%i2) bfloat(2.718281828459045b0)^bfloat(.8618974796837966b0); (%o2) 2.36764899999999983187397393143b0 but: (%i7) bfloat(%e)^bfloat(.8618974796837966b0); (%o7) 2.3676490000000000085638369695b0 surprisingly closer to Python's answer. but 2.718281828459045 isn't e. Close but no cigar. (%i10) bfloat(2.718281828459045b0) - bfloat(%e); (%o10) - 2.35360287471352802147785151603b-16 Fricas: (1) -> 2.718281828459045^0.8618974796837966 (1) 2.3676489999_999998319 (2) -> exp(0.8618974796837966) (2) 2.3676490000_000000086 -- Pieter van Oostrum www: http://pieter.vanoostrum.org/ PGP key: [8DAE142BE17999C4] From kisakyemoses50 at gmail.com Sun Oct 23 11:46:10 2022 From: kisakyemoses50 at gmail.com (Kisakye Moses) Date: Sun, 23 Oct 2022 08:46:10 -0700 (PDT) Subject: Python For TinyML Message-ID: <52e7ac17-3326-4b2f-951b-75826d32af35n@googlegroups.com> Hello am a (M) and glad that I've joined this group. Any help in python for TinyML, i will honored From bowman at montana.com Sun Oct 23 13:23:05 2022 From: bowman at montana.com (rbowman) Date: 23 Oct 2022 17:23:05 GMT Subject: Python For TinyML References: <52e7ac17-3326-4b2f-951b-75826d32af35n@googlegroups.com> Message-ID: On Sun, 23 Oct 2022 08:46:10 -0700 (PDT), Kisakye Moses wrote: > Hello am a (M) and glad that I've joined this group. > Any help in python for TinyML, i will honored https://tinynet.autoai.org/en/latest/ From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 23 16:20:43 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 23 Oct 2022 21:20:43 +0100 Subject: A trivial question that I don't know - document a function/method References: Message-ID: ?s 21:58 de 22/10/22, Paulo da Silva escreveu: > Hi all! > > What is the correct way, if any, of documenting a function/method? > Thank you all for the, valuable as usual, suggestions. I am now able to make my choices. Paulo From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 23 16:36:21 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 23 Oct 2022 21:36:21 +0100 Subject: Typing: Is there a "cast operator"? Message-ID: Hello! I am in the process of "typing" of some of my scripts. Using it should help a lot to avoid some errors. But this is new for me and I'm facing some problems. Let's I have the following code (please don't look at the program content): f=None # mypy naturally assumes Optional(int) because later, at open, it is assigned an int. .. if f is None: f=os.open(... .. if f is not None: os.write(f, ...) .. if f is not None: os.close(f) When I use mypy, it claims Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" How to solve this? Is there a way to specify that when calling os.open f is an int only? I use None a lot for specify uninitialized vars. Thank you. From list1 at tompassin.net Sun Oct 23 17:16:48 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sun, 23 Oct 2022 17:16:48 -0400 Subject: A trivial question that I don't know - document a function/method In-Reply-To: References: <00d39481-3eff-a325-f01d-13e2a7e9acd2@tompassin.net> Message-ID: <83876435-5baf-c2b3-b100-6659a829b104@tompassin.net> On 10/23/2022 2:37 PM, Karsten Hilbert wrote: > Am Sat, Oct 22, 2022 at 09:49:55PM -0400 schrieb Thomas Passin: > >> def make_title_from_headline(self, p, h): >> """From node title, return title with over- and underline- strings. > ... >> RETURNS >> a string >> """ > .... >> def plot(self, stackposition=MAIN, clearFirst=True): >> """Plot a 2-D graph. > ... >> RETURNS >> nothing >> """ > > Would it not, these days, be clearer to > > def make_title_from_headline(self, p, h) -> str: > > def plot(self, stackposition=MAIN, clearFirst=True) -> None: > > and use RETURNS (or Returns:) only when what is returned > warrants further explanation (say, as to what is returned > when). It might, but remember: 1. Knowing the type of a parameter isn't all you usually want to know; 2. If the type information isn't in the docstring, it won't be reported by reporting tools that use the docstring. Then there are all those cases where the signature hasn't been type-annotated, either because adding them to existing code would be a big burden, or because the developer feels it's too much trouble, all things considered. I would say that if the types are annotated, the method is simple enough, and the names are clear enough, sure, go ahead and rely on the type annotations. The most important thing is that readers can understand what the arguments and returns are intended to be, so some flexibility makes sense. From Karsten.Hilbert at gmx.net Sun Oct 23 17:49:22 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Sun, 23 Oct 2022 23:49:22 +0200 Subject: A trivial question that I don't know - document a function/method In-Reply-To: <83876435-5baf-c2b3-b100-6659a829b104@tompassin.net> References: <00d39481-3eff-a325-f01d-13e2a7e9acd2@tompassin.net> <83876435-5baf-c2b3-b100-6659a829b104@tompassin.net> Message-ID: Am Sun, Oct 23, 2022 at 05:16:48PM -0400 schrieb Thomas Passin: > > def make_title_from_headline(self, p, h) -> str: > > > > def plot(self, stackposition=MAIN, clearFirst=True) -> None: > 1. Knowing the type of a parameter isn't all you usually want to know; Sure, as I said: > >and use RETURNS (or Returns:) only when what is returned > >warrants further explanation (say, as to what is returned > >when). same for arguments, which *usually* warrant some further explanation, except for rare cases such as def format_a_string(string2format:str=None) -> str: where string2format just might not require further explanation. > 2. If the type information isn't in the docstring, it won't be reported by reporting > tools that use the docstring. While true such tools could be considered suboptimal (these days, again as I said). > Then there are all those cases where the signature hasn't been type-annotated True but OPs question was *how* to document so there's no perceived problem with having to document. > I would say that if the types are annotated, the method is simple enough, and the names > are clear enough, sure, go ahead and rely on the type annotations. The most important > thing is that readers can understand what the arguments and returns are intended to be, > so some flexibility makes sense. +1 Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From miked at dewhirst.com.au Sun Oct 23 17:46:49 2022 From: miked at dewhirst.com.au (Mike Dewhirst) Date: Mon, 24 Oct 2022 08:46:49 +1100 Subject: Update from 3.9 to 3.10.8 and uninstall 3.9 In-Reply-To: References: Message-ID: On 23/10/2022 9:13 pm, B N wrote: > I am new to python and wish to update 3.9 to3.10.8 which I have downloaded. How do I replace 3.9 with the 3.10.8 I downloaded. > Kind regards > JohnGee It depends on the operating system. Typically, you can just install the new version and adjust your environment vars (ie., path) to point to the new version instead of the old. The theoretical reason is that you may have other programs/scripts etc which still rely on the old version. If you are new to Python, you should probably avoid installing later versions until you have studied virtual environments. A venv will let you keep your "system" Python(s) clean and unencumbered while being able to experiment with all sorts of additional libraries, packages etc in multiple separate sub-environments. Cheers Mike -- Signed email is an absolute defence against phishing. This email has been signed with my private key. If you import my public key you can automatically decrypt my signature and be sure it came from me. Just ask and I'll send it to you. Your email software can handle signing. -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 495 bytes Desc: OpenPGP digital signature URL: From cs at cskk.id.au Sun Oct 23 18:56:07 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 24 Oct 2022 09:56:07 +1100 Subject: Typing: Is there a "cast operator"? In-Reply-To: References: Message-ID: On 23Oct2022 21:36, Paulo da Silva wrote: >I am in the process of "typing" of some of my scripts. >Using it should help a lot to avoid some errors. >But this is new for me and I'm facing some problems. > >Let's I have the following code (please don't look at the program content): > >f=None # mypy naturally assumes Optional(int) because later, at open, >it is assigned an int. >.. >if f is None: > f=os.open(... >.. >if f is not None: > os.write(f, ...) >.. >if f is not None: > os.close(f) > >When I use mypy, it claims >Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" >Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" > >How to solve this? >Is there a way to specify that when calling os.open f is an int only? > >I use None a lot for specify uninitialized vars. Maybe you shouldn't. The other way is to just not initialise the var at all. You could then just specify a type. Example: Python 3.8.13 (default, Aug 11 2022, 15:46:53) [Clang 12.0.0 (clang-1200.0.32.29)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> f:int >>> f Traceback (most recent call last): File "", line 1, in NameError: name 'f' is not defined >>> So now `f` has `int` type definitely (for `mypy`'s purposes), and if used before assignment raises a distinctive error (versus having the value `None`, which you might then pass around, and perhaps successfully use in some contexts). It is probably better on the whole to specify types up front rather than relying on `mypy` or similar to infer them. That way (a) you're stating your intent and (b) not relying on an inferred type, which if you've got bugs may be inferred _wrong_. If `mypy` infers a type incorrectly all the subsequent checks will also be flawed, perhaps subtly. Cheers, Cameron Simpson From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 23 17:36:07 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 23 Oct 2022 22:36:07 +0100 Subject: Typing: Is there a "cast operator"? [RESOLVED] References: Message-ID: ?s 21:36 de 23/10/22, Paulo da Silva escreveu: > Hello! > > I am in the process of "typing" of some of my scripts. > Using it should help a lot to avoid some errors. > But this is new for me and I'm facing some problems. > > Let's I have the following code (please don't look at the program content): > > f=None? # mypy naturally assumes Optional(int) because later, at open, > it is assigned an int. > .. > if f is None: > ????f=os.open(... > .. > if f is not None: > ????os.write(f, ...) > .. > if f is not None: > ????os.close(f) > > When I use mypy, it claims > Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" > Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" > > How to solve this? > Is there a way to specify that when calling os.open f is an int only? And yes there is! Exactly the "cast" operator. A mistype led me to wrong search results. I'm sorry. So, in the above code, we have to do: os.write(cast(int,f), ...) and os.close(cast(int,f), ...) Regards. Paulo From cs at cskk.id.au Sun Oct 23 19:02:10 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 24 Oct 2022 10:02:10 +1100 Subject: need help In-Reply-To: <71D7A169-0438-436F-8F4B-C9F0960DB1AE@hxcore.ol> References: <71D7A169-0438-436F-8F4B-C9F0960DB1AE@hxcore.ol> Message-ID: Please try to choose more descriptive subject lines (eg "problem with sock.connect" or similar). That you want help is almost implicit, and what the whole list is for. Anyway, to your problem: On 23Oct2022 10:19, Shuaib Akhtar wrote: > How to fix Traceback (most recent call last): > ? File "C:\Program > Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\socket.py", > line 833, in create_connection > ??? sock.connect(sa) > TimeoutError: [WinError 10060] A connection attempt failed because > the connected party did not properly respond after a period of time, or > established connection failed because connected host has failed to respond This usually means that either the host address is legal but incorrect (there's no host/server listening with that address) or that the port is incorrect and some firewall is _discarding_ your traffic because of the wrong port instead of returning a nice "connection refused", which is usually instant. Fortunately you've listed your call: > ? File "C:\Users\i9shu\Downloads\python email bot\email bot.py", > line 25, > in > ??? server = smtplib.SMTP('smtp.gmail.com',2525) So, I'll try that by hand here: % telnet smtp.gmail.com 2525 Trying 142.250.4.108... telnet: connect to address 142.250.4.108: Operation timed out Trying 2404:6800:4003:c0f::6d... telnet: connect to address 2404:6800:4003:c0f::6d: No route to host telnet: Unable to connect to remote host % I'd say GMail are rudely dropping traffic to port 2525. Maybe try just 25, the normal SMTP port? Cheers, Cameron Simpson From bowman at montana.com Sun Oct 23 21:02:24 2022 From: bowman at montana.com (rbowman) Date: 24 Oct 2022 01:02:24 GMT Subject: need help References: <71D7A169-0438-436F-8F4B-C9F0960DB1AE@hxcore.ol> Message-ID: On Mon, 24 Oct 2022 10:02:10 +1100, Cameron Simpson wrote: > I'd say GMail are rudely dropping traffic to port 2525. Maybe try just > 25, > the normal SMTP port? 2525 is an alternative to 587, the standard TLS port. 25 and 587 work. telnet smtp.gmail.com 587 Trying 2607:f8b0:4023:1004::6d... Connected to smtp.gmail.com. Escape character is '^]'. 220 smtp.gmail.com ESMTP s6-20020a056870ea8600b0010bf07976c9sm13154711oap. 41 - gsmtp EHLO 501-5.5.4 Empty HELO/EHLO argument not allowed, closing connection. 501 5.5.4 https://support.google.com/mail/?p=helo s6-20020a056870ea8600b0010bf07976c9sm13154711oap.41 - gsmtp Connection closed by foreign host. The EHLO needs a domain. Port 25 is the same. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 23 21:45:45 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Mon, 24 Oct 2022 02:45:45 +0100 Subject: Typing: Is there a "cast operator"? References: Message-ID: ?s 23:56 de 23/10/22, Cameron Simpson escreveu: > On 23Oct2022 21:36, Paulo da Silva > wrote: >> I am in the process of "typing" of some of my scripts. >> Using it should help a lot to avoid some errors. >> But this is new for me and I'm facing some problems. >> >> Let's I have the following code (please don't look at the program >> content): >> >> f=None? # mypy naturally assumes Optional(int) because later, at open, >> it is assigned an int. >> .. >> if f is None: >> ????f=os.open(... >> .. >> if f is not None: >> ????os.write(f, ...) >> .. >> if f is not None: >> ????os.close(f) >> >> When I use mypy, it claims >> Argument 1 to "write" has incompatible type "Optional[int]"; expected >> "int" >> Argument 1 to "close" has incompatible type "Optional[int]"; expected >> "int" >> >> How to solve this? >> Is there a way to specify that when calling os.open f is an int only? >> >> I use None a lot for specify uninitialized vars. > > Maybe you shouldn't. The other way is to just not initialise the var at > all. You could then just specify a type. Example: > > ?? Python 3.8.13 (default, Aug 11 2022, 15:46:53) > ?? [Clang 12.0.0 (clang-1200.0.32.29)] on darwin > ?? Type "help", "copyright", "credits" or "license" for more > information. > ?? >>> f:int > ?? >>> f > ?? Traceback (most recent call last): > ???? File "", line 1, in > ?? NameError: name 'f' is not defined > ?? >>> > > So now `f` has `int` type definitely (for `mypy`'s purposes), and if > used before assignment raises a distinctive error (versus having the > value `None`, which you might then pass around, and perhaps successfully > use in some contexts). > > It is probably better on the whole to specify types up front rather than > relying on `mypy` or similar to infer them. That way (a) you're stating > your intent and (b) not relying on an inferred type, which if you've got > bugs may be inferred _wrong_. If `mypy` infers a type incorrectly all > the subsequent checks will also be flawed, perhaps subtly. > Yes. I also use to make f unavailable (f=None) when something goes wrong and I don't want to stop the script but of course I could use "del f". I also need to care about using "try", which might be better than "if" tests. A thing to think of ... Thanks. Paulo From rosuav at gmail.com Sun Oct 23 22:29:13 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 24 Oct 2022 13:29:13 +1100 Subject: Beautiful Soup - close tags more promptly? Message-ID: Parsing ancient HTML files is something Beautiful Soup is normally great at. But I've run into a small problem, caused by this sort of sloppy HTML: from bs4 import BeautifulSoup # See: https://gsarchive.net/gilbert/plays/princess/tennyson/tenniv.htm blob = b"""
  1. 'THERE sinks the nebulous star we call the Sun,
  2. If that hypothesis of theirs be sound,'
  3. Said Ida;' let us down and rest:' and we
  4. Down from the lean and wrinkled precipices,
  5. By every coppice-feather'd chasm and cleft,
  6. Dropt thro' the ambrosial gloom to where below
  7. No bigger than a glow-worm shone the tent
  8. Lamp-lit from the inner. Once she lean'd on me,
  9. Descending; once or twice she lent her hand,
  10. And blissful palpitations in the blood,
  11. Stirring a sudden transport rose and fell.
""" soup = BeautifulSoup(blob, "html.parser") print(soup) On this small snippet, it works acceptably, but puts a large number of tags immediately before the . On the original file (see link if you want to try it), this blows right through the default recursion limit, due to the crazy number of "nested" list items. Is there a way to tell BS4 on parse that these
  • elements end at the next
  • , rather than waiting for the final ? This would make tidier output, and also eliminate most of the recursion levels. ChrisA From drsalists at gmail.com Sun Oct 23 23:14:15 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Sun, 23 Oct 2022 20:14:15 -0700 Subject: Typing: Is there a "cast operator"? In-Reply-To: References: Message-ID: On Sun, Oct 23, 2022 at 2:11 PM Paulo da Silva < p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > Hello! > > I am in the process of "typing" of some of my scripts. > Using it should help a lot to avoid some errors. > But this is new for me and I'm facing some problems. > > Let's I have the following code (please don't look at the program content): > > f=None # mypy naturally assumes Optional(int) because later, at open, > it is assigned an int. > .. > if f is None: > f=os.open(... > .. > if f is not None: > os.write(f, ...) > .. > if f is not None: > os.close(f) > > When I use mypy, it claims > Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" > Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" > > How to solve this? > Is there a way to specify that when calling os.open f is an int only? > > I use None a lot for specify uninitialized vars. > I've found that mypy understands simple assert statements. So if you: if f is not None: assert f is not None os.write(f, ...) You might be in good shape. From rosuav at gmail.com Sun Oct 23 23:19:37 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 24 Oct 2022 14:19:37 +1100 Subject: Typing: Is there a "cast operator"? In-Reply-To: References: Message-ID: On Mon, 24 Oct 2022 at 14:15, Dan Stromberg wrote: > I've found that mypy understands simple assert statements. > > So if you: > if f is not None: > assert f is not None > os.write(f, ...) > > You might be in good shape. Why can't it simply understand the if statement? I'm not a fan of coddling a type system like this. The entire point of type checking is to help you find bugs more efficiently, so if you have to repeat yourself every time you do these kinds of checks just so that mypy is satisfied, that's counter-productive (case in point: what happens if you say "if fn is not None: assert f is not None"? Now you've introduced a bug just to deal with the type system). ChrisA From cs at cskk.id.au Mon Oct 24 00:01:12 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 24 Oct 2022 15:01:12 +1100 Subject: need help In-Reply-To: References: Message-ID: On 24Oct2022 01:02, rbowman wrote: >On Mon, 24 Oct 2022 10:02:10 +1100, Cameron Simpson wrote: >> I'd say GMail are rudely dropping traffic to port 2525. Maybe try >> just 25, the normal SMTP port? > >2525 is an alternative to 587, the standard TLS port. Yah. My point was more focussed on GMail's shoddy firewall practices not returning connection refused. >25 and 587 work. Good to know. Thanks! Cameron Simpson From list1 at tompassin.net Mon Oct 24 01:24:10 2022 From: list1 at tompassin.net (Thomas Passin) Date: Mon, 24 Oct 2022 01:24:10 -0400 Subject: Typing: Is there a "cast operator"? In-Reply-To: References: Message-ID: <9d3805ae-0acb-65b0-e7d4-3d7bc8a9e170@tompassin.net> On 10/23/2022 11:14 PM, Dan Stromberg wrote: > On Sun, Oct 23, 2022 at 2:11 PM Paulo da Silva < > p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > >> Hello! >> >> I am in the process of "typing" of some of my scripts. >> Using it should help a lot to avoid some errors. >> But this is new for me and I'm facing some problems. >> >> Let's I have the following code (please don't look at the program content): >> >> f=None # mypy naturally assumes Optional(int) because later, at open, >> it is assigned an int. >> .. >> if f is None: >> f=os.open(... >> .. >> if f is not None: >> os.write(f, ...) >> .. >> if f is not None: >> os.close(f) >> >> When I use mypy, it claims >> Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" >> Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" >> >> How to solve this? >> Is there a way to specify that when calling os.open f is an int only? >> >> I use None a lot for specify uninitialized vars. >> > > I've found that mypy understands simple assert statements. > > So if you: > if f is not None: > assert f is not None > os.write(f, ...) > > You might be in good shape. I'm not very familiar with anything but the simplest typing cases as yet, but mypy is happy with these two fragments. if f: os.write(int(f)) # f must be an int if it is not None, so we can cast it to int. Or something like this (substitute write() for print() as needed) - from typing import Optional, Any def f1(x:int)->Optional[int]: if x == 42: return x return None def zprint(arg:Any): if type(arg) == int: print(arg) y0 = f1(0) # None y42 = f1(42) # 42 zprint(y0) # Prints nothing zprint(y42) # Prints 42 Another possibility that mypy is happy with (and probably the simplest) - just declare g:int = None instead of g = None: g: int = None def yprint(arg: int): if arg: yprint(arg) else: print('arg is None') yprint(g) # Prints "arg is None" And **please** let's not go doing this kind of redundant and inelegant construction: if f is not None: assert f is not None os.write(f, ...) From roel at roelschroeven.net Mon Oct 24 03:42:13 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Mon, 24 Oct 2022 09:42:13 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: References: Message-ID: Op 24/10/2022 om 4:29 schreef Chris Angelico: > Parsing ancient HTML files is something Beautiful Soup is normally > great at. But I've run into a small problem, caused by this sort of > sloppy HTML: > > from bs4 import BeautifulSoup > # See: https://gsarchive.net/gilbert/plays/princess/tennyson/tenniv.htm > blob = b""" >
      >
    1. 'THERE sinks the nebulous star we call the Sun, >
    2. If that hypothesis of theirs be sound,' >
    3. Said Ida;' let us down and rest:' and we >
    4. Down from the lean and wrinkled precipices, >
    5. By every coppice-feather'd chasm and cleft, >
    6. Dropt thro' the ambrosial gloom to where below >
    7. No bigger than a glow-worm shone the tent >
    8. Lamp-lit from the inner. Once she lean'd on me, >
    9. Descending; once or twice she lent her hand, >
    10. And blissful palpitations in the blood, >
    11. Stirring a sudden transport rose and fell. >
    > """ > soup = BeautifulSoup(blob, "html.parser") > print(soup) > > > On this small snippet, it works acceptably, but puts a large number of >
  • tags immediately before the . On the original file (see > link if you want to try it), this blows right through the default > recursion limit, due to the crazy number of "nested" list items. > > Is there a way to tell BS4 on parse that these
  • elements end at > the next
  • , rather than waiting for the final ? This would > make tidier output, and also eliminate most of the recursion levels. > Using html5lib (install package html5lib) instead of html.parser seems to do the trick: it inserts
  • right before the next
  • , and one before the closing . On my system the same happens when I don't specify a parser, but IIRC that's a bit fragile because other systems can choose different parsers of you don't explicity specify one. -- "I love science, and it pains me to think that to so many are terrified of the subject or feel that choosing science means you cannot also choose compassion, or the arts, or be awed by nature. Science is not meant to cure us of mystery, but to reinvent and reinvigorate it." -- Robert Sapolsky From rosuav at gmail.com Mon Oct 24 04:02:15 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 24 Oct 2022 19:02:15 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: References: Message-ID: On Mon, 24 Oct 2022 at 18:43, Roel Schroeven wrote: > > Op 24/10/2022 om 4:29 schreef Chris Angelico: > > Parsing ancient HTML files is something Beautiful Soup is normally > > great at. But I've run into a small problem, caused by this sort of > > sloppy HTML: > > > > from bs4 import BeautifulSoup > > # See: https://gsarchive.net/gilbert/plays/princess/tennyson/tenniv.htm > > blob = b""" > >
      > >
    1. 'THERE sinks the nebulous star we call the Sun, > >
    2. If that hypothesis of theirs be sound,' > >
    3. Said Ida;' let us down and rest:' and we > >
    4. Down from the lean and wrinkled precipices, > >
    5. By every coppice-feather'd chasm and cleft, > >
    6. Dropt thro' the ambrosial gloom to where below > >
    7. No bigger than a glow-worm shone the tent > >
    8. Lamp-lit from the inner. Once she lean'd on me, > >
    9. Descending; once or twice she lent her hand, > >
    10. And blissful palpitations in the blood, > >
    11. Stirring a sudden transport rose and fell. > >
    > > """ > > soup = BeautifulSoup(blob, "html.parser") > > print(soup) > > > > > > On this small snippet, it works acceptably, but puts a large number of > >
  • tags immediately before the . On the original file (see > > link if you want to try it), this blows right through the default > > recursion limit, due to the crazy number of "nested" list items. > > > > Is there a way to tell BS4 on parse that these
  • elements end at > > the next
  • , rather than waiting for the final ? This would > > make tidier output, and also eliminate most of the recursion levels. > > > Using html5lib (install package html5lib) instead of html.parser seems > to do the trick: it inserts
  • right before the next
  • , and one > before the closing . On my system the same happens when I don't > specify a parser, but IIRC that's a bit fragile because other systems > can choose different parsers of you don't explicity specify one. > Ah, cool. Thanks. I'm not entirely sure of the various advantages and disadvantages of the different parsers; is there a tabulation anywhere, or at least a list of recommendations on choosing a suitable parser? I'm dealing with a HUGE mess of different coding standards, all the way from 1990s-level stuff (images for indentation, tables for formatting, and ) up through HTML4 (a good few of the pages have at least some tags and declare their encodings, mostly ISO-8859-1 or similar), to fairly modern HTML5. There's even a couple of pages that use frames - yes, the old style with a block in case the browser can't handle it. I went with html.parser on the expectation that it'd give the best "across all standards" results, but I'll give html5lib a try and see if it does better. Would rather not try to use different parsers for different files, but if necessary, I'll figure something out. (For reference, this is roughly 9000 HTML files that have to be parsed. Doing things by hand is basically not an option.) ChrisA From roel at roelschroeven.net Mon Oct 24 04:09:36 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Mon, 24 Oct 2022 10:09:36 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <c4e38efe-15f2-9081-a51e-96e17cd797a5@roelschroeven.net> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <c4e38efe-15f2-9081-a51e-96e17cd797a5@roelschroeven.net> Message-ID: <5cf17806-fc33-ec22-cae4-c1dcfed39f3e@roelschroeven.net> Op 24/10/2022 om 9:42 schreef Roel Schroeven: > Using html5lib (install package html5lib) instead of html.parser seems > to do the trick: it inserts </li> right before the next <li>, and one > before the closing </ol> . On my system the same happens when I don't > specify a parser, but IIRC that's a bit fragile because other systems > can choose different parsers of you don't explicity specify one. Just now I noticed: when I don't specify a parser, BeautifulSoup emits a warning with the parser it selected. In one of my venv's it's html5lib, in another it's lxml. Both seem to get a correct result. -- "I love science, and it pains me to think that to so many are terrified of the subject or feel that choosing science means you cannot also choose compassion, or the arts, or be awed by nature. Science is not meant to cure us of mystery, but to reinvent and reinvigorate it." -- Robert Sapolsky From roel at roelschroeven.net Mon Oct 24 04:33:00 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Mon, 24 Oct 2022 10:33:00 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmopmn8wxaQyZ2H83WNr-TjOxPRymKKtK3ddXiSZfYrBhA@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <c4e38efe-15f2-9081-a51e-96e17cd797a5@roelschroeven.net> <CAPTjJmopmn8wxaQyZ2H83WNr-TjOxPRymKKtK3ddXiSZfYrBhA@mail.gmail.com> Message-ID: <a52acc4d-74e8-2eb8-a69f-b24889e4f0bf@roelschroeven.net> (Oops, accidentally only sent to Chris instead of to the list) Op 24/10/2022 om 10:02 schreef Chris Angelico: > On Mon, 24 Oct 2022 at 18:43, Roel Schroeven <roel at roelschroeven.net> > wrote: > > Using html5lib (install package html5lib) instead of html.parser seems > > to do the trick: it inserts </li> right before the next <li>, and one > > before the closing </ol> . On my system the same happens when I don't > > specify a parser, but IIRC that's a bit fragile because other systems > > can choose different parsers of you don't explicity specify one. > > > > Ah, cool. Thanks. I'm not entirely sure of the various advantages and > disadvantages of the different parsers; is there a tabulation > anywhere, or at least a list of recommendations on choosing a suitable > parser? There's a bit of information here: https://beautiful-soup-4.readthedocs.io/en/latest/#installing-a-parser Not much but maybe it can be helpful. > I'm dealing with a HUGE mess of different coding standards, all the > way from 1990s-level stuff (images for indentation, tables for > formatting, and <FONT FACE="Wingdings">) up through HTML4 (a good few > of the pages have at least some <meta> tags and declare their > encodings, mostly ISO-8859-1 or similar), to fairly modern HTML5. > There's even a couple of pages that use frames - yes, the old style > with a <noframes> block in case the browser can't handle it. I went > with html.parser on the expectation that it'd give the best "across > all standards" results, but I'll give html5lib a try and see if it > does better. > > Would rather not try to use different parsers for different files, but > if necessary, I'll figure something out. > > (For reference, this is roughly 9000 HTML files that have to be > parsed. Doing things by hand is basically not an option.) > I'd give lxml a try too. Maybe try to preprocess the HTML using html-tidy (https://www.html-tidy.org/), that might actually do a pretty good job of getting rid of all kinds of historical inconsistencies. Somehow checking if any solution works for thousands of input files will always be a pain, I'm afraid. -- "I've come up with a set of rules that describe our reactions to technologies: 1. Anything that is in the world when you?re born is normal and ordinary and is just a natural part of the way the world works. 2. Anything that's invented between when you?re fifteen and thirty-five is new and exciting and revolutionary and you can probably get a career in it. 3. Anything invented after you're thirty-five is against the natural order of things." -- Douglas Adams, The Salmon of Doubt From hjp-python at hjp.at Mon Oct 24 05:33:45 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 24 Oct 2022 11:33:45 +0200 Subject: need help In-Reply-To: <jrm6h0Fm14qU2@mid.individual.net> References: <71D7A169-0438-436F-8F4B-C9F0960DB1AE@hxcore.ol> <Y1XH8rMkodx6+3nS@cskk.homeip.net> <mailman.776.1666566134.20444.python-list@python.org> <jrm6h0Fm14qU2@mid.individual.net> Message-ID: <20221024093345.j4sfh3pps2dfen2o@hjp.at> On 2022-10-24 01:02:24 +0000, rbowman wrote: > On Mon, 24 Oct 2022 10:02:10 +1100, Cameron Simpson wrote: > > I'd say GMail are rudely dropping traffic to port 2525. Maybe try just > > 25, > > the normal SMTP port? > > 2525 is an alternative to 587, the standard TLS port. Port 587 is not the standard TLS port. Port 587 is the standard mail submission port (i.e., a MUA should use port 587 when sending mail; MTAs should use port 25 when relaying mails to other MTAs). Traffic on both port 25 and 587 starts in plain text. The server can indicate that it supports TLS and the client can then send a STARTTLS command to start a TLS session. If you want to start the connection with TLS, you can (usually) use port 465. Like 587, this is only intended for mail submission, not mail transport. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221024/6fbb324f/attachment.sig> From hjp-python at hjp.at Mon Oct 24 06:32:11 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 24 Oct 2022 12:32:11 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> Message-ID: <20221024103211.hrisphe3xdwjqcbb@hjp.at> On 2022-10-24 13:29:13 +1100, Chris Angelico wrote: > Parsing ancient HTML files is something Beautiful Soup is normally > great at. But I've run into a small problem, caused by this sort of > sloppy HTML: > > from bs4 import BeautifulSoup > # See: https://gsarchive.net/gilbert/plays/princess/tennyson/tenniv.htm > blob = b""" > <OL> > <LI>'THERE sinks the nebulous star we call the Sun, > <LI>If that hypothesis of theirs be sound,' [...] > <LI>Stirring a sudden transport rose and fell. > </OL> > """ > soup = BeautifulSoup(blob, "html.parser") > print(soup) > > > On this small snippet, it works acceptably, but puts a large number of > </li> tags immediately before the </ol>. Ron has already noted that the lxml and html5 parser do the right thing, so just for the record: The HTML fragment above is well-formed and contains a number of li elements at the same level directly below the ol element, not lots of nested li elements. The end tag of the li element is optional (except in XHTML) and li elements don't nest. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221024/0c158494/attachment.sig> From hjp-python at hjp.at Mon Oct 24 06:34:56 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 24 Oct 2022 12:34:56 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <20221024103211.hrisphe3xdwjqcbb@hjp.at> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> Message-ID: <20221024103456.2nev7e2hqgrf5qld@hjp.at> On 2022-10-24 12:32:11 +0200, Peter J. Holzer wrote: > Ron has already noted that the lxml and html5 parser do the right thing, ^^^ Oops, sorry. That was Roel. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221024/43b51511/attachment.sig> From rosuav at gmail.com Mon Oct 24 06:56:13 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 24 Oct 2022 21:56:13 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <20221024103211.hrisphe3xdwjqcbb@hjp.at> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> Message-ID: <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> On Mon, 24 Oct 2022 at 21:33, Peter J. Holzer <hjp-python at hjp.at> wrote: > Ron has already noted that the lxml and html5 parser do the right thing, > so just for the record: > > The HTML fragment above is well-formed and contains a number of li > elements at the same level directly below the ol element, not lots of > nested li elements. The end tag of the li element is optional (except in > XHTML) and li elements don't nest. That's correct. However, parsing it with html.parser and then reconstituting it as shown in the example code results in all the </li> tags coming up right before the </ol>, indicating that the <li> tags were parsed as deeply nested rather than as siblings. In order to get a successful parse out of this, I need something which sees them as siblings, which html5lib seems to be doing fine. Whether it has other issues, I don't know, but I guess I'll find out.... it's currently running on the live site and taking several hours (due to network delays and the server being slow, so I don't really want to parallelize and overload the thing). ChrisA From hjp-python at hjp.at Mon Oct 24 08:21:34 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 24 Oct 2022 14:21:34 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> Message-ID: <20221024122134.2mfuckmeyshj4ceg@hjp.at> On 2022-10-24 21:56:13 +1100, Chris Angelico wrote: > On Mon, 24 Oct 2022 at 21:33, Peter J. Holzer <hjp-python at hjp.at> wrote: > > Ron has already noted that the lxml and html5 parser do the right thing, > > so just for the record: > > > > The HTML fragment above is well-formed and contains a number of li > > elements at the same level directly below the ol element, not lots of > > nested li elements. The end tag of the li element is optional (except in > > XHTML) and li elements don't nest. > > That's correct. However, parsing it with html.parser and then > reconstituting it as shown in the example code results in all the > </li> tags coming up right before the </ol>, indicating that the <li> > tags were parsed as deeply nested rather than as siblings. Yes, I got that. What I wanted to say was that this is indeed a bug in html.parser and not an error (or sloppyness, as you called it) in the input or ambiguity in the HTML standard. > In order to get a successful parse out of this, I need something which > sees them as siblings, Right, but Roel (correct name this time) had already posted that lxml and html5lib parse this correctly, so I saw no need to belabour that point. > which html5lib seems to be doing fine. Whether > it has other issues, I don't know, but I guess I'll find out.... The link somebody posted mentions that it's "very slow". Which may or may not be a problem when you have to parse 9000 files. But if it does implement HTML5 correctly, it should parse any file the same as a modern browser does (maybe excluding quirks mode). hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221024/af4a94d5/attachment.sig> From Joseph.Schachner at Teledyne.com Mon Oct 24 09:07:58 2022 From: Joseph.Schachner at Teledyne.com (Schachner, Joseph (US)) Date: Mon, 24 Oct 2022 13:07:58 +0000 Subject: A trivial question that I don't know - document a function/method In-Reply-To: <tj1lh1$1tnj$1@gioia.aioe.org> References: <tj1lh1$1tnj$1@gioia.aioe.org> Message-ID: <BN8PR14MB2851951421D32A1E76CB8BF1F52E9@BN8PR14MB2851.namprd14.prod.outlook.com> I head a small software team much of whose output is Python. I would gratefully accept any of the formats you show below. My preference is #1. --- Joseph S. Teledyne Confidential; Commercially Sensitive Business Data -----Original Message----- From: Paulo da Silva <p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> Sent: Saturday, October 22, 2022 4:58 PM To: python-list at python.org Subject: A trivial question that I don't know - document a function/method Hi all! What is the correct way, if any, of documenting a function/method? 1. def foo(a,b): """ A description. a: Whatever 1 b: Whatever 2 """ ... 2. def foo(a,b): """ A description. a -- Whatever 1 b -- Whatever 2 """ ... 3. def foo(a,b): """ A description. @param a: Whatever 1 @param b: Whatever 2 """ ... 4. def foo(a,b): """ A description. :param a: Whatever 1 :param b: Whatever 2 """ ... 5. Any other ... Any comments/suggestions are welcome. Thanks. Paulo From rosuav at gmail.com Mon Oct 24 10:01:19 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 25 Oct 2022 01:01:19 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <20221024122134.2mfuckmeyshj4ceg@hjp.at> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> Message-ID: <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> On Mon, 24 Oct 2022 at 23:22, Peter J. Holzer <hjp-python at hjp.at> wrote: > > On 2022-10-24 21:56:13 +1100, Chris Angelico wrote: > > On Mon, 24 Oct 2022 at 21:33, Peter J. Holzer <hjp-python at hjp.at> wrote: > > > Ron has already noted that the lxml and html5 parser do the right thing, > > > so just for the record: > > > > > > The HTML fragment above is well-formed and contains a number of li > > > elements at the same level directly below the ol element, not lots of > > > nested li elements. The end tag of the li element is optional (except in > > > XHTML) and li elements don't nest. > > > > That's correct. However, parsing it with html.parser and then > > reconstituting it as shown in the example code results in all the > > </li> tags coming up right before the </ol>, indicating that the <li> > > tags were parsed as deeply nested rather than as siblings. > > Yes, I got that. What I wanted to say was that this is indeed a bug in > html.parser and not an error (or sloppyness, as you called it) in the > input or ambiguity in the HTML standard. I described the HTML as "sloppy" for a number of reasons, but I was of the understanding that it's generally recommended to have the closing tags. Not that it matters much. > > which html5lib seems to be doing fine. Whether > > it has other issues, I don't know, but I guess I'll find out.... > > The link somebody posted mentions that it's "very slow". Which may or > may not be a problem when you have to parse 9000 files. But if it does > implement HTML5 correctly, it should parse any file the same as a modern > browser does (maybe excluding quirks mode). > Yeah. TBH I think the two-hour run time is primarily dominated by network delays, not parsing time, but if I had a service where people could upload HTML to be parsed, that might affect throughput. For the record, if anyone else is considering html5lib: It is likely "fast enough", even if not fast. Give it a try. (And I know what slow parsing feels like. Parsing a ~100MB file with a decently-fast grammar-based lexer takes a good while. Parsing the same content after it's been converted to JSON? Fast.) ChrisA From reto at slightlybroken.com Mon Oct 24 01:06:44 2022 From: reto at slightlybroken.com (Reto) Date: Mon, 24 Oct 2022 07:06:44 +0200 Subject: score function in linear regression model In-Reply-To: <0b2b86f6-2235-4996-83e3-0da69b3f3c76n@googlegroups.com> References: <0b2b86f6-2235-4996-83e3-0da69b3f3c76n@googlegroups.com> Message-ID: <20221024050644.zf3tlxrs3nofbe4r@feather> On Sun, Oct 23, 2022 at 05:11:10AM -0700, Fatemeh Heydari wrote: > model.score(X,Y) That will basically check how good your model is. It takes a bunch of X values with known values, which you provide in Y and compares the output of model.Predict(X) with the Y's and gives you some metrics as to how good that performed. In the case of linear regression that be R^2, the coefficient of determination of the prediction. Cheers, Reto From kisakyemoses50 at gmail.com Mon Oct 24 10:01:30 2022 From: kisakyemoses50 at gmail.com (Kisakye Moses) Date: Mon, 24 Oct 2022 07:01:30 -0700 (PDT) Subject: Python For TinyML In-Reply-To: <jrlbjpFi408U3@mid.individual.net> References: <52e7ac17-3326-4b2f-951b-75826d32af35n@googlegroups.com> <jrlbjpFi408U3@mid.individual.net> Message-ID: <955afdde-e38a-4c4a-a020-3ee2b9c5c2a6n@googlegroups.com> On Sunday, October 23, 2022 at 8:23:26 PM UTC+3, rbowman wrote: > On Sun, 23 Oct 2022 08:46:10 -0700 (PDT), Kisakye Moses wrote: > > > Hello am a (M) and glad that I've joined this group. > > Any help in python for TinyML, i will honored > https://tinynet.autoai.org/en/latest/ Thank you so much From Joseph.Schachner at Teledyne.com Mon Oct 24 10:52:28 2022 From: Joseph.Schachner at Teledyne.com (Schachner, Joseph (US)) Date: Mon, 24 Oct 2022 14:52:28 +0000 Subject: Are Floating Point Numbers still a Can of Worms? In-Reply-To: <m2bkq24nyd.fsf@vanoostrum.org> References: <acba3501-fe4b-496d-8ebc-90eb2dc81c54n@googlegroups.com> <769f670e-92b4-401e-8d9e-4b8d12a0925dn@googlegroups.com> <m2bkq24nyd.fsf@vanoostrum.org> Message-ID: <BN8PR14MB28516217D40F209CD968E434F52E9@BN8PR14MB2851.namprd14.prod.outlook.com> Floating point will always be a can of worms, as long as people expect it to represent real numbers with more precision that float has. Usually this is not an issue, but sometimes it is. And, although this example does not exhibit subtractive cancellation, that is the surest way to have less precision that the two values you subtracted. And if you try to add up lots of values, if your sum grows large enough, tiny values will not change it anymore, even if there are many of them - there are simple algorithms to avoid this effect. But all of this is because float has limited precision. --- Joseph S. Teledyne Confidential; Commercially Sensitive Business Data -----Original Message----- From: Pieter van Oostrum <pieter-l at vanoostrum.org> Sent: Sunday, October 23, 2022 10:25 AM To: python-list at python.org Subject: Re: Are Floating Point Numbers still a Can of Worms? Mostowski Collapse <bursejan at gmail.com> writes: > I also get: > > Python 3.11.0rc1 (main, Aug 8 2022, 11:30:54) >>>> 2.718281828459045**0.8618974796837966 > 2.367649 > > Nice try, but isn't this one the more correct? > > ?- X is 2.718281828459045**0.8618974796837966. > X = 2.3676489999999997. > That's probably the accuracy of the underlying C implementation of the exp function. In [25]: exp(0.8618974796837966) Out[25]: 2.367649 But even your answer can be improved: Maxima: (%i1) fpprec:30$ (%i2) bfloat(2.718281828459045b0)^bfloat(.8618974796837966b0); (%o2) 2.36764899999999983187397393143b0 but: (%i7) bfloat(%e)^bfloat(.8618974796837966b0); (%o7) 2.3676490000000000085638369695b0 surprisingly closer to Python's answer. but 2.718281828459045 isn't e. Close but no cigar. (%i10) bfloat(2.718281828459045b0) - bfloat(%e); (%o10) - 2.35360287471352802147785151603b-16 Fricas: (1) -> 2.718281828459045^0.8618974796837966 (1) 2.3676489999_999998319 (2) -> exp(0.8618974796837966) (2) 2.3676490000_000000086 -- Pieter van Oostrum <pieter at vanoostrum.org> www: http://pieter.vanoostrum.org/ PGP key: [8DAE142BE17999C4] From jon+usenet at unequivocal.eu Mon Oct 24 11:34:45 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Mon, 24 Oct 2022 15:34:45 -0000 (UTC) Subject: Beautiful Soup - close tags more promptly? References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> Message-ID: <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> On 2022-10-24, Chris Angelico <rosuav at gmail.com> wrote: > On Mon, 24 Oct 2022 at 23:22, Peter J. Holzer <hjp-python at hjp.at> wrote: >> Yes, I got that. What I wanted to say was that this is indeed a bug in >> html.parser and not an error (or sloppyness, as you called it) in the >> input or ambiguity in the HTML standard. > > I described the HTML as "sloppy" for a number of reasons, but I was of > the understanding that it's generally recommended to have the closing > tags. Not that it matters much. Some elements don't need close tags, or even open tags. Unless you're using XHTML you don't need them and indeed for the case of void tags (e.g. <br>, <img>) you must not include the close tags. A minimal HTML file might look like this: <!DOCTYPE html> <html lang=en><meta charset=utf-8><title>Minimal HTML file</title> <main><h1>Minimal HTML file</h1>This is a minimal HTML file.</main> which would be parsed into this: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Minimal HTML file</title> </head> <body> <main> <h1>Minimal HTML file</h1> This is a minimal HTML file. </main> </body> </html> Adding in the omitted <head>, </head>, <body>, </body>, and </html> would make no difference and there's no particular reason to recommend doing so as far as I'm aware. From rosuav at gmail.com Mon Oct 24 12:09:33 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 25 Oct 2022 03:09:33 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> Message-ID: <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> On Tue, 25 Oct 2022 at 02:45, Jon Ribbens via Python-list <python-list at python.org> wrote: > > On 2022-10-24, Chris Angelico <rosuav at gmail.com> wrote: > > On Mon, 24 Oct 2022 at 23:22, Peter J. Holzer <hjp-python at hjp.at> wrote: > >> Yes, I got that. What I wanted to say was that this is indeed a bug in > >> html.parser and not an error (or sloppyness, as you called it) in the > >> input or ambiguity in the HTML standard. > > > > I described the HTML as "sloppy" for a number of reasons, but I was of > > the understanding that it's generally recommended to have the closing > > tags. Not that it matters much. > > Some elements don't need close tags, or even open tags. Unless you're > using XHTML you don't need them and indeed for the case of void tags > (e.g. <br>, <img>) you must not include the close tags. Yep, I'm aware of void tags, but I'm talking about the container tags - in this case, <li> and <p> - which, in a lot of older HTML pages, are treated as "separator" tags. Consider this content: <HTML> Hello, world! <P> Paragraph 2 <P> Hey look, a third paragraph! </HTML> Stick a doctype onto that and it should be valid HTML5, but as it is, it's the exact sort of thing that was quite common in the 90s. (I'm not sure when lowercase tags became more popular, but in any case (pun intended), that won't affect validity.) The <p> tag is not a void tag, but according to the spec, it's legal to omit the </p> if the element is followed directly by another <p> element (or any of a specific set of others), or if there is no further content. > Adding in the omitted <head>, </head>, <body>, </body>, and </html> > would make no difference and there's no particular reason to recommend > doing so as far as I'm aware. And yet most people do it. Why? Are you saying that it's better to omit them all? More importantly: Would you omit all the </p> closing tags you can, or would you include them? ChrisA From mats at wichmann.us Mon Oct 24 13:17:29 2022 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 24 Oct 2022 11:17:29 -0600 Subject: A trivial question that I don't know - document a function/method In-Reply-To: <tj47ms$9ea$1@gioia.aioe.org> References: <tj1lh1$1tnj$1@gioia.aioe.org> <tj47ms$9ea$1@gioia.aioe.org> Message-ID: <a5fedb62-275c-e8ed-1bda-d8639ae1e786@wichmann.us> On 10/23/22 14:20, Paulo da Silva wrote: > ?s 21:58 de 22/10/22, Paulo da Silva escreveu: >> Hi all! >> >> What is the correct way, if any, of documenting a function/method? >> > > Thank you all for the, valuable as usual, suggestions. > I am now able to make my choices. > > Paulo It also matters whether you expect the docstring to stand on its own, or to be processed by a doc-generation tool (like Sphinx). In the former case, make it look nice in a way that suits you. In the latter case, use the reStructuredText conventions that exist (there are at least three common styles) for the document processor. While these styles are intended to also be very human-readable, they may not be exactly how you wanted to format things for visual display when looking directly at code, so it's worth thinking about this up front. See for example: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html From hjp-python at hjp.at Mon Oct 24 13:17:55 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 24 Oct 2022 19:17:55 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> Message-ID: <20221024171755.2skumphjochke2sd@hjp.at> On 2022-10-25 03:09:33 +1100, Chris Angelico wrote: > On Tue, 25 Oct 2022 at 02:45, Jon Ribbens via Python-list > <python-list at python.org> wrote: > > On 2022-10-24, Chris Angelico <rosuav at gmail.com> wrote: > > > On Mon, 24 Oct 2022 at 23:22, Peter J. Holzer <hjp-python at hjp.at> wrote: > > >> Yes, I got that. What I wanted to say was that this is indeed a bug in > > >> html.parser and not an error (or sloppyness, as you called it) in the > > >> input or ambiguity in the HTML standard. > > > > > > I described the HTML as "sloppy" for a number of reasons, but I was of > > > the understanding that it's generally recommended to have the closing > > > tags. Not that it matters much. > > > > Some elements don't need close tags, or even open tags. Unless you're > > using XHTML you don't need them and indeed for the case of void tags > > (e.g. <br>, <img>) you must not include the close tags. > > Yep, I'm aware of void tags, but I'm talking about the container tags > - in this case, <li> and <p> - which, in a lot of older HTML pages, > are treated as "separator" tags. Consider this content: > > <HTML> > Hello, world! > <P> > Paragraph 2 > <P> > Hey look, a third paragraph! > </HTML> > > Stick a doctype onto that and it should be valid HTML5, but as it is, > it's the exact sort of thing that was quite common in the 90s. > > The <p> tag is not a void tag, but according to the spec, it's legal > to omit the </p> if the element is followed directly by another <p> > element (or any of a specific set of others), or if there is no > further content. Right. The parser knows the structure of an HTML document, which tags are optional and which elements can be inside of which other elements. For SGML-based HTML versions (2.0 to 4.01) this is formally described by the DTD. So when parsing your file, an HTML parser would work like this <HTML> - Yup, I expect an HTML element here: HTML Hello, world! - #PCDATA? Not allowed as a child of HTML. There must be a HEAD and a BODY, both of which have optional start tags. HEAD can't contain #PCDATA either, so we must be inside of BODY and HEAD was empty: HTML ?? HEAD ?? BODY ?? Hello, world! <P> - Allowed in BODY, so just add that: HTML ?? HEAD ?? BODY ?? #PCDATA: Hello, world! ?? P Paragraph 2 - #PCDATA is allowed in P, so add it as a child: HTML ?? HEAD ?? BODY ?? #PCDATA: Hello, world! ?? P ?? #PCDATA: Paragraph 2 <P> - Not allowed inside of P, so that implicitely closes the previous P element and we go up one level: HTML ?? HEAD ?? BODY ?? #PCDATA: Hello, world! ?? P ? ?? #PCDATA: Paragraph 2 ?? P Hey look, a third paragraph! - Same as above: HTML ?? HEAD ?? BODY ?? #PCDATA: Hello, world! ?? P ? ?? #PCDATA: Paragraph 2 ?? P ?? #PCDATA: Hey look, a third paragraph! </HTML> - The end tags of P and BODY are optional, so the end of HTML closes them implicitely, and we have our final parse tree (unchanged from the last step): HTML ?? HEAD ?? BODY ?? #PCDATA: Hello, world! ?? P ? ?? #PCDATA: Paragraph 2 ?? P ?? #PCDATA: Hey look, a third paragraph! For a human, the <p> tags might feel like separators here. But syntactically they aren't - they start a new element. Note especially that "Hello, world!" is not part of a P element but a direct child of BODY (which may or may not be intended by the author). > > > Adding in the omitted <head>, </head>, <body>, </body>, and </html> > > would make no difference and there's no particular reason to recommend > > doing so as far as I'm aware. > > And yet most people do it. Why? There may be several reasons: * Historically, some browsers differed in which end tags were actually optional. Since (AFAIK) no mainstream browser ever implemented a real SGML parser (they were always "tag soup" parsers with lots of ad-hoc rules) this sometimes even changed within the same browser depending on context (e.g. a simple table might work but nested tables woudn't). So people started to use end-tags defensively. * XHTML was for some time popular and it doesn't have any optional tags. So people got into the habit of always using end tags and writing empty tags as <XXX />. * Aesthetics: Always writing the end tags is more consistent and may look more balanced. * Cargo-cult: People saw other people do that and copied the habit without thinking about it. > Are you saying that it's better to omit them all? If you want to conserve keystrokes :-) I think it doesn't matter. Both are valid. > More importantly: Would you omit all the </p> closing tags you can, or > would you include them? I usually write them. I also indent the contents of an element, so I would write your example as: <!DOCTYPE html> <html> <body> Hello, world! <p> Paragraph 2 </p> <p> Hey look, a third paragraph! </p> </body> </html> (As you can see I would also include the body tags to make that element explicit. I would normally also add a bit of boilerplate (especially a head with a charset and viewport definition), but I omit them here since they would change the parse tree) hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221024/1b043256/attachment.sig> From jon+usenet at unequivocal.eu Mon Oct 24 13:01:00 2022 From: jon+usenet at unequivocal.eu (Jon Ribbens) Date: Mon, 24 Oct 2022 17:01:00 -0000 (UTC) Subject: Beautiful Soup - close tags more promptly? References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> <mailman.795.1666627787.20444.python-list@python.org> Message-ID: <slrntldh6c.50r.jon+usenet@raven.unequivocal.eu> On 2022-10-24, Chris Angelico <rosuav at gmail.com> wrote: > On Tue, 25 Oct 2022 at 02:45, Jon Ribbens via Python-list ><python-list at python.org> wrote: >> >> On 2022-10-24, Chris Angelico <rosuav at gmail.com> wrote: >> > On Mon, 24 Oct 2022 at 23:22, Peter J. Holzer <hjp-python at hjp.at> wrote: >> >> Yes, I got that. What I wanted to say was that this is indeed a bug in >> >> html.parser and not an error (or sloppyness, as you called it) in the >> >> input or ambiguity in the HTML standard. >> > >> > I described the HTML as "sloppy" for a number of reasons, but I was of >> > the understanding that it's generally recommended to have the closing >> > tags. Not that it matters much. >> >> Some elements don't need close tags, or even open tags. Unless you're >> using XHTML you don't need them and indeed for the case of void tags >> (e.g. <br>, <img>) you must not include the close tags. > > Yep, I'm aware of void tags, but I'm talking about the container tags > - in this case, <li> and <p> - which, in a lot of older HTML pages, > are treated as "separator" tags. Yes, hence why I went on to talk about container tags. > Consider this content: > ><HTML> > Hello, world! ><P> > Paragraph 2 ><P> > Hey look, a third paragraph! ></HTML> > > Stick a doctype onto that and it should be valid HTML5, Nope, it's missing a <title>. >> Adding in the omitted <head>, </head>, <body>, </body>, and </html> >> would make no difference and there's no particular reason to recommend >> doing so as far as I'm aware. > > And yet most people do it. Why? They agree with Tim Peters that "Explicit is better than implicit", I suppose? ;-) > Are you saying that it's better to omit them all? No, I'm saying it's neither option is necessarily better than the other. > More importantly: Would you omit all the </p> closing tags you can, or > would you include them? It would depend on how much content was inside them I guess. Something like: <ol> <li>First item <li>Second item <li>Third item </ol> is very easy to understand, but if each item was many lines long then it may be less confusing to explicitly close - not least for indentation purposes. From roel at roelschroeven.net Mon Oct 24 14:10:34 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Mon, 24 Oct 2022 20:10:34 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <slrntldh6c.50r.jon+usenet@raven.unequivocal.eu> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> <mailman.795.1666627787.20444.python-list@python.org> <slrntldh6c.50r.jon+usenet@raven.unequivocal.eu> Message-ID: <2a485e88-bd22-4cef-c87d-ea9f06ee60bb@roelschroeven.net> Jon Ribbens via Python-list schreef op 24/10/2022 om 19:01: > On 2022-10-24, Chris Angelico<rosuav at gmail.com> wrote: > > On Tue, 25 Oct 2022 at 02:45, Jon Ribbens via Python-list <python-list at python.org> wrote: > >> Adding in the omitted <head>, </head>, <body>, </body>, and </html> > >> would make no difference and there's no particular reason to recommend > >> doing so as far as I'm aware. > > > > And yet most people do it. Why? > > They agree with Tim Peters that "Explicit is better than implicit", > I suppose? ;-) I don't write all that much HTML, but when I do, it include those tags largely for that reason indeed. We don't write HTML just for the browser, we also write it for the web developer. And I think it's easier for the web developer when the different sections are clearly distinguished, and what better way to do it than use their tags. >> > More importantly: Would you omit all the </p> closing tags you can, or >> > would you include them? > It would depend on how much content was inside them I guess. > Something like: > > <ol> > <li>First item > <li>Second item > <li>Third item > </ol> > > is very easy to understand, but if each item was many lines long then it > may be less confusing to explicitly close - not least for indentation > purposes. I mostly include closing tags, if for no other reason than that I have the impression that editors generally work better (i.e. get things like indentation and syntax highlighting right) that way. -- "Je ne suis pas d?accord avec ce que vous dites, mais je me battrai jusqu?? la mort pour que vous ayez le droit de le dire." -- Attribu? ? Voltaire "I disapprove of what you say, but I will defend to the death your right to say it." -- Attributed to Voltaire "Ik ben het niet eens met wat je zegt, maar ik zal je recht om het te zeggen tot de dood toe verdedigen" -- Toegeschreven aan Voltaire From jschwar at sbcglobal.net Mon Oct 24 14:16:02 2022 From: jschwar at sbcglobal.net (jschwar at sbcglobal.net) Date: Mon, 24 Oct 2022 13:16:02 -0500 Subject: python 3.11 References: <007e01d8e7d4$ae0cd830$0a268890$.ref@sbcglobal.net> Message-ID: <007e01d8e7d4$ae0cd830$0a268890$@sbcglobal.net> Is python 3.11 still being release today? Just wondering. Not sure when during the day this is done. Thanks. From wlfraed at ix.netcom.com Mon Oct 24 14:02:33 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 24 Oct 2022 14:02:33 -0400 Subject: Are Floating Point Numbers still a Can of Worms? References: <acba3501-fe4b-496d-8ebc-90eb2dc81c54n@googlegroups.com> <769f670e-92b4-401e-8d9e-4b8d12a0925dn@googlegroups.com> <m2bkq24nyd.fsf@vanoostrum.org> <BN8PR14MB28516217D40F209CD968E434F52E9@BN8PR14MB2851.namprd14.prod.outlook.com> <mailman.794.1666623225.20444.python-list@python.org> Message-ID: <rmkdlh5hc561dptkan4u67ei4pq1tar1a5@4ax.com> On Mon, 24 Oct 2022 14:52:28 +0000, "Schachner, Joseph (US)" <Joseph.Schachner at Teledyne.com> declaimed the following: >Floating point will always be a can of worms, as long as people expect it to represent real numbers with more precision that float has. Usually this is not an issue, but sometimes it is. And, although this example does not exhibit subtractive cancellation, that is the surest way to have less precision that the two values you subtracted. And if you try to add up lots of values, if your sum grows large enough, tiny values will not change it anymore, even if there are many of them - there are simple algorithms to avoid this effect. But all of this is because float has limited precision. > Might I suggest this to those affected... https://www.amazon.com/Real-Computing-Made-Engineering-Calculations/dp/0486442217/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1666634371&sr=8-1 (Wow -- they want a fortune for the original hard-cover, which I own) -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From rosuav at gmail.com Mon Oct 24 15:56:58 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 25 Oct 2022 06:56:58 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <20221024171755.2skumphjochke2sd@hjp.at> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> <20221024171755.2skumphjochke2sd@hjp.at> Message-ID: <CAPTjJmpThvOHwu8t-edKuVEP=nySG1xAdHNJkh+QD4gauSnynA@mail.gmail.com> On Tue, 25 Oct 2022 at 04:22, Peter J. Holzer <hjp-python at hjp.at> wrote: > There may be several reasons: > > * Historically, some browsers differed in which end tags were actually > optional. Since (AFAIK) no mainstream browser ever implemented a real > SGML parser (they were always "tag soup" parsers with lots of ad-hoc > rules) this sometimes even changed within the same browser depending > on context (e.g. a simple table might work but nested tables woudn't). > So people started to use end-tags defensively. > * XHTML was for some time popular and it doesn't have any optional tags. > So people got into the habit of always using end tags and writing > empty tags as <XXX />. > * Aesthetics: Always writing the end tags is more consistent and may > look more balanced. > * Cargo-cult: People saw other people do that and copied the habit > without thinking about it. > > > > Are you saying that it's better to omit them all? > > If you want to conserve keystrokes :-) > > I think it doesn't matter. Both are valid. > > > More importantly: Would you omit all the </p> closing tags you can, or > > would you include them? > > I usually write them. Interesting. So which of the above reasons is yours? Personally, I do it for a slightly different reason: Many end tags are *situationally* optional, and it's much easier to debug code when you change/insert/remove something and nothing changes, than when doing so affects the implicit closing tags. > I also indent the contents of an element, so I > would write your example as: > > <!DOCTYPE html> > <html> > <body> > Hello, world! > <p> > Paragraph 2 > </p> > <p> > Hey look, a third paragraph! > </p> > </body> > </html> > > (As you can see I would also include the body tags to make that element > explicit. I would normally also add a bit of boilerplate (especially a > head with a charset and viewport definition), but I omit them here since > they would change the parse tree) > Yeah - any REAL page would want quite a bit (very few pages these days manage without a style sheet, and it seems that hardly any survive without importing a few gigabytes of JavaScript, but that's not mandatory), but in ancient pages, there's still a well-defined parse structure for every tag sequences. One thing I find quite interesting, though, is the way that browsers *differ* in the face of bad nesting of tags. Recently I was struggling to figure out a problem with an HTML form, and eventually found that there was a spurious <form> tag way up higher in the page. Forms don't nest, so that's invalid, but different browsers had slightly different ways of showing it. (Obviously the W3C Validator was the most helpful tool here, since it reports it as an error rather than constructing any sort of DOM tree.) ChrisA From pablogsal at gmail.com Mon Oct 24 16:26:54 2022 From: pablogsal at gmail.com (Pablo Galindo Salgado) Date: Mon, 24 Oct 2022 21:26:54 +0100 Subject: [RELEASE] Python 3.11 final (3.11.0) is available Message-ID: <CAFjbc8HYzs9hL7cKs4YntSagvn9Zjcikzt5Y3=G8EWfgVTJnsg@mail.gmail.com> Python 3.11 is finally released. In the CPython release team, we have put a lot of effort into making 3.11 the best version of Python possible. Better tracebacks, faster Python, exception groups and except*, typing improvements and much more. Get it here: https://www.python.org/downloads/release/python-3110/ ## This is the stable release of Python 3.11.0 Python 3.11.0 is the newest major release of the Python programming language, and it contains many new features and optimizations. # Major new features of the 3.11 series, compared to 3.10 Some of the new major new features and changes in Python 3.11 are: ## General changes * [PEP 657](https://www.python.org/dev/peps/pep-0657/) -- Include Fine-Grained Error Locations in Tracebacks * [PEP 654](https://www.python.org/dev/peps/pep-0654/) -- Exception Groups and `except*` * [PEP 680](https://www.python.org/dev/peps/pep-0680/) -- tomllib: Support for Parsing TOML in the Standard Library * [gh-90908](https://github.com/python/cpython/issues/90908) -- Introduce task groups to asyncio * [gh-34627](https://github.com/python/cpython/issues/34627/) -- Atomic grouping (`(?>...)`) and possessive quantifiers (`*+, ++, ?+, {m,n}+`) are now supported in regular expressions. * The [Faster CPython Project](https://github.com/faster-cpython/) is already yielding some exciting results. Python 3.11 is up to 10-60% faster than Python 3.10. On average, we measured a 1.22x speedup on the standard benchmark suite. See [Faster CPython]( https://docs.python.org/3.11/whatsnew/3.11.html#faster-cpython) for details. ## Typing and typing language changes * [PEP 673](https://www.python.org/dev/peps/pep-0673/) -- Self Type * [PEP 646](https://www.python.org/dev/peps/pep-0646/) -- Variadic Generics * [PEP 675](https://www.python.org/dev/peps/pep-0675/) -- Arbitrary Literal String Type * [PEP 655](https://www.python.org/dev/peps/pep-0655/) -- Marking individual TypedDict items as required or potentially-missing * [PEP 681](https://www.python.org/dev/peps/pep-0681/) -- Data Class Transforms # More resources * [Online Documentation](https://docs.python.org/3.11/) * [PEP 664](https://www.python.org/dev/peps/pep-0664/), 3.11 Release Schedule * Report bugs at [ https://github.com/python/cpython/issues](https://github.com/python/cpython/issues) . * [Help fund Python and its community](/psf/donations/). # And now for something completely different When a spherical non-rotating body of a critical radius collapses under its own gravitation under general relativity, theory suggests it will collapse to a single point. This is not the case with a rotating black hole (a Kerr black hole). With a fluid rotating body, its distribution of mass is not spherical (it shows an equatorial bulge), and it has angular momentum. Since a point cannot support rotation or angular momentum in classical physics (general relativity being a classical theory), the minimal shape of the singularity that can support these properties is instead a ring with zero thickness but non-zero radius, and this is referred to as a ringularity or Kerr singularity. This kind of singularity has the following peculiar property. The spacetime allows a geodesic curve (describing the movement of observers and photons in spacetime) to pass through the center of this ring singularity. The region beyond permits closed time-like curves. Since the trajectory of observers and particles in general relativity are described by time-like curves, it is possible for observers in this region to return to their past. This interior solution is not likely to be physical and is considered a purely mathematical artefact. There are some other interesting free-fall trajectories. For example, there is a point in the axis of symmetry that has the property that if an observer is below this point, the pull from the singularity will force the observer to pass through the middle of the ring singularity to the region with closed time-like curves and it will experience repulsive gravity that will push it back to the original region, but then it will experience the pull from the singularity again and will repeat this process forever. This is, of course, only if the extreme gravity doesn?t destroy the observer first. # We hope you enjoy the new releases! Thanks to all of the many volunteers who help make Python Development and these releases possible! Please consider supporting our efforts by volunteering yourself or through organization contributions to the Python Software Foundation. https://www.python.org/psf/ If you have any questions, please reach out to me or another member of the release team :) Your friendly release team, Ned Deily @nad https://discuss.python.org/u/nad Steve Dower @steve.dower https://discuss.python.org/u/steve.dower Pablo Galindo Salgado @pablogsal https://discuss.python.org/u/pablogsal From barry at barrys-emacs.org Mon Oct 24 16:52:12 2022 From: barry at barrys-emacs.org (Barry Scott) Date: Mon, 24 Oct 2022 21:52:12 +0100 Subject: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) In-Reply-To: <SA1PR14MB5855B09F91EF5250E297E9D4B95E9@SA1PR14MB5855.namprd14.prod.outlook.com> References: <f583eefa-ef36-a59b-7b33-928d67e49f06@mrabarnett.plus.com> <FC32E4B4-6B96-44BC-ACE6-C0EF2E93242B@barrys-emacs.org> <SA1PR14MB5855B09F91EF5250E297E9D4B95E9@SA1PR14MB5855.namprd14.prod.outlook.com> Message-ID: <BD2A58F7-9C8F-418E-A02B-5B70CAC0D481@barrys-emacs.org> > On 8 Oct 2022, at 11:50, Weatherby,Gerard <gweatherby at uchc.edu> wrote: > > Logging does support passing a callable, if indirectly. It only calls __str__ on the object passed if debugging is enabled. > > class Defer: > > def __init__(self,fn): > self.fn = fn > > def __str__(self): > return self.fn() > > def some_expensive_function(): > return "hello" > > logging.basicConfig() > logging.debug(Defer(some_expensive_function)) Oh what a clever hack. Took a few minutes of code reading to see why this works. You are exploiting the str(msg) that is in class LogRecords getMessage(). ``` def getMessage(self): """ Return the message for this LogRecord. Return the message for this LogRecord after merging any user-supplied arguments with the message. """ msg = str(self.msg) if self.args: msg = msg % self.args return msg ``` Barry > > > From: Python-list <python-list-bounces+gweatherby=uchc.edu at python.org <mailto:python-list-bounces+gweatherby=uchc.edu at python.org>> on behalf of Barry <barry at barrys-emacs.org <mailto:barry at barrys-emacs.org>> > Date: Friday, October 7, 2022 at 1:30 PM > To: MRAB <python at mrabarnett.plus.com <mailto:python at mrabarnett.plus.com>> > Cc: python-list at python.org <mailto:python-list at python.org> <python-list at python.org <mailto:python-list at python.org>> > Subject: Re: Ref-strings in logging messages (was: Performance issue with CPython 3.10 + Cython) > > *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** > > > On 7 Oct 2022, at 18:16, MRAB <python at mrabarnett.plus.com> wrote: > > > > ?On 2022-10-07 16:45, Skip Montanaro wrote: > >>> On Fri, Oct 7, 2022 at 9:42 AM Andreas Ames <andreas.0815.qwertz at gmail.com> > >>> wrote: > >>> 1. The culprit was me. As lazy as I am, I have used f-strings all over the > >>> place in calls to `logging.logger.debug()` and friends, evaluating all > >>> arguments regardless of whether the logger was enabled or not. > >>> > >> I thought there was some discussion about whether and how to efficiently > >> admit f-strings to the logging package. I'm guessing that's not gone > >> anywhere (yet). > > Letting you pass in a callable to call might help because that you could use lambda. > > Yep, that?s the obvious way to avoid expensive log data generation. > Would need logging module to support that use case. > > Barry > > > -- > > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ <https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$> > > > > -- > https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$ <https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mrESxAj9YCHsdtNAfkNiY-Zf6U3WTIqaNrgBmbw1ELlQy51ilob43dD0ONsqvg4a94MEdOdwomgyqfyABbvRnA$> From hjp-python at hjp.at Mon Oct 24 18:33:11 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Tue, 25 Oct 2022 00:33:11 +0200 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmpThvOHwu8t-edKuVEP=nySG1xAdHNJkh+QD4gauSnynA@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> <20221024171755.2skumphjochke2sd@hjp.at> <CAPTjJmpThvOHwu8t-edKuVEP=nySG1xAdHNJkh+QD4gauSnynA@mail.gmail.com> Message-ID: <20221024223311.igtoadnn6d2ceae4@hjp.at> On 2022-10-25 06:56:58 +1100, Chris Angelico wrote: > On Tue, 25 Oct 2022 at 04:22, Peter J. Holzer <hjp-python at hjp.at> wrote: > > There may be several reasons: > > > > * Historically, some browsers differed in which end tags were actually > > optional. Since (AFAIK) no mainstream browser ever implemented a real > > SGML parser (they were always "tag soup" parsers with lots of ad-hoc > > rules) this sometimes even changed within the same browser depending > > on context (e.g. a simple table might work but nested tables woudn't). > > So people started to use end-tags defensively. > > * XHTML was for some time popular and it doesn't have any optional tags. > > So people got into the habit of always using end tags and writing > > empty tags as <XXX />. > > * Aesthetics: Always writing the end tags is more consistent and may > > look more balanced. > > * Cargo-cult: People saw other people do that and copied the habit > > without thinking about it. > > > > > > > Are you saying that it's better to omit them all? > > > > If you want to conserve keystrokes :-) > > > > I think it doesn't matter. Both are valid. > > > > > More importantly: Would you omit all the </p> closing tags you can, or > > > would you include them? > > > > I usually write them. > > Interesting. So which of the above reasons is yours? Mostly the third one at this point I think. The first one has gone away for me with HTML5. The second one still lingers at the back of my brain, but I've gotten rid of the habit of writing <img .../>, so I'm recevering ;-). But I still like my code to be nice and tidy, and whether my sense of tidyness was influenced by XML or not, if the end tags are missing it looks off, somehow. (That said, I do sometimes leave them off to reduce visual clutter.) > One thing I find quite interesting, though, is the way that browsers > *differ* in the face of bad nesting of tags. Recently I was struggling > to figure out a problem with an HTML form, and eventually found that > there was a spurious <form> tag way up higher in the page. Forms don't > nest, so that's invalid, but different browsers had slightly different > ways of showing it. Yeah, mismatched form tags can have weird effects. I don't remember the details but I scratched my head over that one more than once. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221025/9fe3860c/attachment.sig> From rosuav at gmail.com Mon Oct 24 18:57:07 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 25 Oct 2022 09:57:07 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <20221024223311.igtoadnn6d2ceae4@hjp.at> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <20221024103211.hrisphe3xdwjqcbb@hjp.at> <CAPTjJmqW3x5+KqH-zk93QC9fLgzROeGt0_R-Oxrhx0Rr8X91Fw@mail.gmail.com> <20221024122134.2mfuckmeyshj4ceg@hjp.at> <CAPTjJmoBBan1GQAeuJDb8dwR+5VmC23E68th+2SdcucB-3GH6g@mail.gmail.com> <mailman.792.1666620093.20444.python-list@python.org> <slrntldc4l.50r.jon+usenet@raven.unequivocal.eu> <CAPTjJmo7PQrXxG0K+4tKwkpz-fteNyF8Xr5EdhRs3pfL+8Ua9g@mail.gmail.com> <20221024171755.2skumphjochke2sd@hjp.at> <CAPTjJmpThvOHwu8t-edKuVEP=nySG1xAdHNJkh+QD4gauSnynA@mail.gmail.com> <20221024223311.igtoadnn6d2ceae4@hjp.at> Message-ID: <CAPTjJmps6-6sQ5nk2tZO-5MwqU5NA_A=zeFrGWgojGw=jZX7tA@mail.gmail.com> On Tue, 25 Oct 2022 at 09:34, Peter J. Holzer <hjp-python at hjp.at> wrote: > > One thing I find quite interesting, though, is the way that browsers > > *differ* in the face of bad nesting of tags. Recently I was struggling > > to figure out a problem with an HTML form, and eventually found that > > there was a spurious <form> tag way up higher in the page. Forms don't > > nest, so that's invalid, but different browsers had slightly different > > ways of showing it. > > Yeah, mismatched form tags can have weird effects. I don't remember the > details but I scratched my head over that one more than once. > Yeah. I think my weirdest issue was one time when I inadvertently had a <dialog> element (with a form inside it) inside something else with a form (because the </form> was missing). Neither "dialog inside main" nor "form in dialog separate from form in main" is a problem, and even "oops, missed a closing form tag" isn't that big a deal, but put them all together, and you end up with a bizarre situation where Firefox 91 behaves one way and Chrome (some-version) behaves another way. That was a fun day. Remember, folks, even if you think you ran the W3C validator on your code recently, it can still be worth checking. Just in case. ChrisA From nospam at dfs.com Tue Oct 25 13:03:58 2022 From: nospam at dfs.com (DFS) Date: Tue, 25 Oct 2022 13:03:58 -0400 Subject: Any PyQt developers here? Message-ID: <1GU5L.400518$9Yp5.247552@fx12.iad> Having problems with removeRow() on a QTableView object. After calling removeRow(), the screen isn't updating. It's as if the model is read-only, but it's a QSqlTableModel() model, which is not read-only. The underlying SQL is straightforward (one table) and all columns are editable. None of the editStrategies are working either. I tried everything I can think of, including changes to the EditTriggers, but no luck. HELP! FWIW, the same removeRow() code works fine with a QTableWidget. ------------------------------------------------------------------- object creation and data loading all works fine ------------------------------------------------------------------- #open db connection qdb = QSqlDatabase.addDatabase("QSQLITE") qdb.setDatabaseName(dbname) qdb.open() #prepare query and execute to return data query = QSqlQuery() query.prepare(cSQL) query.exec_() #set model type and query model = QSqlTableModel() model.setQuery(query) #assign model to QTableView object view = frm.tblPostsView view.setModel(model) #get all data while(model.canFetchMore()): model.fetchMore() datarows = model.rowCount() ------------------------------------------------------------------- iterate selected rows also works fine SelectionMode is Extended. identical code works for a QTableWidget ------------------------------------------------------------------- selected = tbl.selectionModel().selectedRows() #reverse sort the selected items to delete from bottom up selected = sorted(selected,reverse=True) for i,val in enumerate(selected): tbl.model().removeRow(selected[i].row()) From list1 at tompassin.net Tue Oct 25 13:45:04 2022 From: list1 at tompassin.net (Thomas Passin) Date: Tue, 25 Oct 2022 13:45:04 -0400 Subject: Any PyQt developers here? In-Reply-To: <1GU5L.400518$9Yp5.247552@fx12.iad> References: <1GU5L.400518$9Yp5.247552@fx12.iad> Message-ID: <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> On 10/25/2022 1:03 PM, DFS wrote: > Having problems with removeRow() on a QTableView object. removeRow() isn't listed as being a method of a QTableView, not even an inherited method, so how are you calling removeRow() on it? (See https://doc.qt.io/qt-6/qtableview-members.html) > After calling removeRow(), the screen isn't updating.? It's as if the > model is read-only, but it's a QSqlTableModel() model, which is not > read-only. > > The underlying SQL is straightforward (one table) and all columns are > editable. > > None of the editStrategies are working either. > > I tried everything I can think of, including changes to the > EditTriggers, but no luck.? HELP! > > FWIW, the same removeRow() code works fine with a QTableWidget. > > ------------------------------------------------------------------- > object creation and data loading all works fine > ------------------------------------------------------------------- > #open db connection > qdb = QSqlDatabase.addDatabase("QSQLITE") > qdb.setDatabaseName(dbname) > qdb.open() > > #prepare query and execute to return data > query = QSqlQuery() > query.prepare(cSQL) > query.exec_() > > #set model type and query > model = QSqlTableModel() > model.setQuery(query) > > #assign model to QTableView object > view = frm.tblPostsView > view.setModel(model) > > #get all data > while(model.canFetchMore()): model.fetchMore() > datarows = model.rowCount() > > > > ------------------------------------------------------------------- > iterate selected rows also works fine > SelectionMode is Extended. > identical code works for a QTableWidget > ------------------------------------------------------------------- > selected = tbl.selectionModel().selectedRows() > #reverse sort the selected items to delete from bottom up > selected = sorted(selected,reverse=True) > for i,val in enumerate(selected): > ????tbl.model().removeRow(selected[i].row()) > From joni.j.ekholm at gmail.com Tue Oct 25 13:47:34 2022 From: joni.j.ekholm at gmail.com (Joni Ekholm) Date: Tue, 25 Oct 2022 20:47:34 +0300 Subject: Python 3.11 with Pygame Message-ID: <CAJx0-kt+VsN8C_0v-xZp_mQK1OSAUZRnyTQtbi6NV+c98-vqrg@mail.gmail.com> Hi, Does Pygame work with 3.11? with 3.10 no problems. Br Joni From timothy.c.delaney at gmail.com Tue Oct 25 13:59:02 2022 From: timothy.c.delaney at gmail.com (Tim Delaney) Date: Wed, 26 Oct 2022 04:59:02 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAPTjJmopmn8wxaQyZ2H83WNr-TjOxPRymKKtK3ddXiSZfYrBhA@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <c4e38efe-15f2-9081-a51e-96e17cd797a5@roelschroeven.net> <CAPTjJmopmn8wxaQyZ2H83WNr-TjOxPRymKKtK3ddXiSZfYrBhA@mail.gmail.com> Message-ID: <CAN8CLg=ko1R9Csuf33znVJD1KoG4uJBcUeiAFCkDk4vG7MTQSQ@mail.gmail.com> On Mon, 24 Oct 2022 at 19:03, Chris Angelico <rosuav at gmail.com> wrote: > > Ah, cool. Thanks. I'm not entirely sure of the various advantages and > disadvantages of the different parsers; is there a tabulation > anywhere, or at least a list of recommendations on choosing a suitable > parser? > Coming to this a bit late, but from my experience with BeautifulSoup and HTML produced by other people ... lxml is easily the fastest, but also the least forgiving. html.parer is middling on performance, but as you've seen sometimes makes mistakes. html5lib is the slowest, but is most forgiving of malformed input and edge cases. I use html5lib - it's fast enough for what I do, and the most likely to return results matching what the author saw when they maybe tried it in a single web browser. Tim Delaney From rosuav at gmail.com Tue Oct 25 14:03:25 2022 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 26 Oct 2022 05:03:25 +1100 Subject: Beautiful Soup - close tags more promptly? In-Reply-To: <CAN8CLg=ko1R9Csuf33znVJD1KoG4uJBcUeiAFCkDk4vG7MTQSQ@mail.gmail.com> References: <CAPTjJmor6s9eOrkKr71oPh1Du-migmk5tBd0wz6Zy--TG7+sJA@mail.gmail.com> <c4e38efe-15f2-9081-a51e-96e17cd797a5@roelschroeven.net> <CAPTjJmopmn8wxaQyZ2H83WNr-TjOxPRymKKtK3ddXiSZfYrBhA@mail.gmail.com> <CAN8CLg=ko1R9Csuf33znVJD1KoG4uJBcUeiAFCkDk4vG7MTQSQ@mail.gmail.com> Message-ID: <CAPTjJmqtUW=vQ3xO0iyQt9LjObgOtksSsK9b_LmiuwuzC-04ow@mail.gmail.com> On Wed, 26 Oct 2022 at 04:59, Tim Delaney <timothy.c.delaney at gmail.com> wrote: > > On Mon, 24 Oct 2022 at 19:03, Chris Angelico <rosuav at gmail.com> wrote: >> >> >> Ah, cool. Thanks. I'm not entirely sure of the various advantages and >> disadvantages of the different parsers; is there a tabulation >> anywhere, or at least a list of recommendations on choosing a suitable >> parser? > > > Coming to this a bit late, but from my experience with BeautifulSoup and HTML produced by other people ... > > lxml is easily the fastest, but also the least forgiving. > html.parer is middling on performance, but as you've seen sometimes makes mistakes. > html5lib is the slowest, but is most forgiving of malformed input and edge cases. > > I use html5lib - it's fast enough for what I do, and the most likely to return results matching what the author saw when they maybe tried it in a single web browser. Cool cool. It sounds like html5lib should really be the recommended parser for HTML, unless performance or dependency reduction is important enough to change your plans. (But only for HTML. For XML, lxml would still be the right choice.) ChrisA From barry at barrys-emacs.org Tue Oct 25 14:03:57 2022 From: barry at barrys-emacs.org (Barry Scott) Date: Tue, 25 Oct 2022 19:03:57 +0100 Subject: Any PyQt developers here? In-Reply-To: <1GU5L.400518$9Yp5.247552@fx12.iad> References: <1GU5L.400518$9Yp5.247552@fx12.iad> Message-ID: <0E65B029-0D91-448D-B59D-E5F4EC9D21E9@barrys-emacs.org> There is an active PyQt mailing list that has lots of helpful and knowledgeable people on it. https://www.riverbankcomputing.com/mailman/listinfo/pyqt Barry > On 25 Oct 2022, at 18:03, DFS <nospam at dfs.com> wrote: > > Having problems with removeRow() on a QTableView object. > > After calling removeRow(), the screen isn't updating. It's as if the model is read-only, but it's a QSqlTableModel() model, which is not read-only. > > The underlying SQL is straightforward (one table) and all columns are editable. > > None of the editStrategies are working either. > > I tried everything I can think of, including changes to the EditTriggers, but no luck. HELP! > > FWIW, the same removeRow() code works fine with a QTableWidget. > > ------------------------------------------------------------------- > object creation and data loading all works fine > ------------------------------------------------------------------- > #open db connection > qdb = QSqlDatabase.addDatabase("QSQLITE") > qdb.setDatabaseName(dbname) > qdb.open() > > #prepare query and execute to return data > query = QSqlQuery() > query.prepare(cSQL) > query.exec_() > > #set model type and query > model = QSqlTableModel() > model.setQuery(query) > > #assign model to QTableView object > view = frm.tblPostsView > view.setModel(model) > > #get all data > while(model.canFetchMore()): model.fetchMore() > datarows = model.rowCount() > > > > ------------------------------------------------------------------- > iterate selected rows also works fine > SelectionMode is Extended. > identical code works for a QTableWidget > ------------------------------------------------------------------- > selected = tbl.selectionModel().selectedRows() > #reverse sort the selected items to delete from bottom up > selected = sorted(selected,reverse=True) > for i,val in enumerate(selected): > tbl.model().removeRow(selected[i].row()) > > -- > https://mail.python.org/mailman/listinfo/python-list > From barry at barrys-emacs.org Tue Oct 25 13:59:06 2022 From: barry at barrys-emacs.org (Barry Scott) Date: Tue, 25 Oct 2022 18:59:06 +0100 Subject: UTF-8 and latin1 In-Reply-To: <guess-20221025111453@ram.dialup.fu-berlin.de> References: <tdj0t2$19v7$1@gioia.aioe.org> <encoding-20220817163204@ram.dialup.fu-berlin.de> <guess-20221025111453@ram.dialup.fu-berlin.de> Message-ID: <C81AE64A-06B9-4B38-A629-E79F00E77AEE@barrys-emacs.org> > On 25 Oct 2022, at 11:16, Stefan Ram <ram at zedat.fu-berlin.de> wrote: > > ram at zedat.fu-berlin.de (Stefan Ram) writes: >> You can let Python guess the encoding of a file. >> def encoding_of( name ): >> path = pathlib.Path( name ) >> for encoding in( "utf_8", "cp1252", "latin_1" ): >> try: >> with path.open( encoding=encoding, errors="strict" )as file: > > I also read a book which claimed that the tkinter.Text > widget would accept bytes and guess whether these are > encoded in UTF-8 or "ISO 8859-1" and decode them > accordingly. However, today I found that here it does > accept bytes but it always guesses "ISO 8859-1". The best you can do is assume that if the text cannot decode as utf-8 it may be 8859-1. Barry > > main.py > > import tkinter > > text = tkinter.Text() > text.insert( tkinter.END, "A???????".encode( encoding='ISO 8859-1' )) > text.insert( tkinter.END, "A???????".encode( encoding='UTF-8' )) > text.pack() > print( text.get( "1.0", "end" )) > > output > > A???????A?????????????? > > > -- > https://mail.python.org/mailman/listinfo/python-list From mats at wichmann.us Tue Oct 25 15:13:08 2022 From: mats at wichmann.us (Mats Wichmann) Date: Tue, 25 Oct 2022 13:13:08 -0600 Subject: Python 3.11 with Pygame In-Reply-To: <CAJx0-kt+VsN8C_0v-xZp_mQK1OSAUZRnyTQtbi6NV+c98-vqrg@mail.gmail.com> References: <CAJx0-kt+VsN8C_0v-xZp_mQK1OSAUZRnyTQtbi6NV+c98-vqrg@mail.gmail.com> Message-ID: <0ff761fd-d0f7-0641-5014-135e0e961e8a@wichmann.us> On 10/25/22 11:47, Joni Ekholm wrote: > Hi, > > Does Pygame work with 3.11? with 3.10 no problems. > > Br Joni It often takes a while for projects with binary wheels to to catch up to new Python releases. You can always go check: https://pypi.org/project/pygame/#files From that, it seems there aren't 3.11 wheels yet. From rosuav at gmail.com Tue Oct 25 17:05:09 2022 From: rosuav at gmail.com (Chris Angelico) Date: Wed, 26 Oct 2022 08:05:09 +1100 Subject: UTF-8 and latin1 In-Reply-To: <C81AE64A-06B9-4B38-A629-E79F00E77AEE@barrys-emacs.org> References: <tdj0t2$19v7$1@gioia.aioe.org> <encoding-20220817163204@ram.dialup.fu-berlin.de> <guess-20221025111453@ram.dialup.fu-berlin.de> <C81AE64A-06B9-4B38-A629-E79F00E77AEE@barrys-emacs.org> Message-ID: <CAPTjJmqocQZ5YAhA+2+=kJCnYaUmQe7GAMX3JpNEhiG7C4fDpg@mail.gmail.com> On Wed, 26 Oct 2022 at 05:09, Barry Scott <barry at barrys-emacs.org> wrote: > > > > > On 25 Oct 2022, at 11:16, Stefan Ram <ram at zedat.fu-berlin.de> wrote: > > > > ram at zedat.fu-berlin.de (Stefan Ram) writes: > >> You can let Python guess the encoding of a file. > >> def encoding_of( name ): > >> path = pathlib.Path( name ) > >> for encoding in( "utf_8", "cp1252", "latin_1" ): > >> try: > >> with path.open( encoding=encoding, errors="strict" )as file: > > > > I also read a book which claimed that the tkinter.Text > > widget would accept bytes and guess whether these are > > encoded in UTF-8 or "ISO 8859-1" and decode them > > accordingly. However, today I found that here it does > > accept bytes but it always guesses "ISO 8859-1". > > The best you can do is assume that if the text cannot decode as utf-8 it may be 8859-1. > Except when it's Windows-1252. ChrisA From __peter__ at web.de Wed Oct 26 08:44:29 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 26 Oct 2022 14:44:29 +0200 Subject: Typing: Is there a "cast operator"? In-Reply-To: <CAPTjJmrQusAzr3hZkJPkJfpCuWO3ZPbQ4yr8K-F5FLg+Z9Q-Ww@mail.gmail.com> References: <tj48k6$ndp$1@gioia.aioe.org> <CAGGBd_o=yYXqoef_JoAEFKsdEO_ER=UTYtsTdbh9TRf6irrP7g@mail.gmail.com> <CAPTjJmrQusAzr3hZkJPkJfpCuWO3ZPbQ4yr8K-F5FLg+Z9Q-Ww@mail.gmail.com> Message-ID: <ec8cdd94-daec-0dfd-7c29-c8aa638ff1d4@web.de> On 24/10/2022 05:19, Chris Angelico wrote: > On Mon, 24 Oct 2022 at 14:15, Dan Stromberg <drsalists at gmail.com> wrote: >> I've found that mypy understands simple assert statements. >> >> So if you: >> if f is not None: >> assert f is not None >> os.write(f, ...) >> >> You might be in good shape. > > Why can't it simply understand the if statement? Could it be that this specific problem is fixed in current mypy? I get $ type .\tmp.py import os f = None if f is None: f = os.open("tmp.txt", os.O_RDWR|os.O_CREAT) os.write(f, b"yadda") $ mypy tmp.py Success: no issues found in 1 source file My attempt to verify that if name is None: ... is recognized: $ type .\tmp2.py import os import random f = None if random.randrange(2): f = os.open("tmp.txt", os.O_RDWR|os.O_CREAT) os.write(f, b"yadda") $ mypy tmp2.py tmp2.py:7: error: Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" Found 1 error in 1 file (checked 1 source file) $ mypy --version mypy 0.982 (compiled: yes) $ I'm not a fan of > coddling a type system like this. The entire point of type checking is > to help you find bugs more efficiently, so if you have to repeat > yourself every time you do these kinds of checks just so that mypy is > satisfied, that's counter-productive (case in point: what happens if > you say "if fn is not None: assert f is not None"? Now you've > introduced a bug just to deal with the type system). > > ChrisA From nospam at dfs.com Tue Oct 25 15:19:48 2022 From: nospam at dfs.com (DFS) Date: Tue, 25 Oct 2022 15:19:48 -0400 Subject: Any PyQt developers here? In-Reply-To: <mailman.805.1666719919.20444.python-list@python.org> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> Message-ID: <oFW5L.450337$wLZ8.409011@fx18.iad> On 10/25/2022 1:45 PM, Thomas Passin wrote: > On 10/25/2022 1:03 PM, DFS wrote: >> Having problems with removeRow() on a QTableView object. > > removeRow() isn't listed as being a method of a QTableView, not even an > inherited method, so how are you calling removeRow() on it? (See > https://doc.qt.io/qt-6/qtableview-members.html) * I thought I was calling it the same way it's called with QTableWidgets: tbl.removeRow() But looking at my code again I was using tbl.model().removeRow() * Plus I found several others online with similar removeRow() issues with QTableViews. * Plus the code didn't throw an error: selected = tbl.selectionModel().selectedRows() #reverse sort the selected items to delete from bottom up selected = sorted(selected,reverse=True) for i,val in enumerate(selected): tbl.model().removeRow(selected[i].row()) But... as you say, when looking at the docs, removeRow() isn't even one of the slots for QTableViews. So duh! I see the QTableView.hideRow(row) method, which does exactly what I need. Thanks man! >> After calling removeRow(), the screen isn't updating.? It's as if the >> model is read-only, but it's a QSqlTableModel() model, which is not >> read-only. >> >> The underlying SQL is straightforward (one table) and all columns are >> editable. >> >> None of the editStrategies are working either. >> >> I tried everything I can think of, including changes to the >> EditTriggers, but no luck.? HELP! >> >> FWIW, the same removeRow() code works fine with a QTableWidget. >> >> ------------------------------------------------------------------- >> object creation and data loading all works fine >> ------------------------------------------------------------------- >> #open db connection >> qdb = QSqlDatabase.addDatabase("QSQLITE") >> qdb.setDatabaseName(dbname) >> qdb.open() >> >> #prepare query and execute to return data >> query = QSqlQuery() >> query.prepare(cSQL) >> query.exec_() >> >> #set model type and query >> model = QSqlTableModel() >> model.setQuery(query) >> >> #assign model to QTableView object >> view = frm.tblPostsView >> view.setModel(model) >> >> #get all data >> while(model.canFetchMore()): model.fetchMore() >> datarows = model.rowCount() >> >> >> >> ------------------------------------------------------------------- >> iterate selected rows also works fine >> SelectionMode is Extended. >> identical code works for a QTableWidget >> ------------------------------------------------------------------- >> selected = tbl.selectionModel().selectedRows() >> #reverse sort the selected items to delete from bottom up >> selected = sorted(selected,reverse=True) >> for i,val in enumerate(selected): >> ?????tbl.model().removeRow(selected[i].row()) >> > From nospam at dfs.com Tue Oct 25 15:20:34 2022 From: nospam at dfs.com (DFS) Date: Tue, 25 Oct 2022 15:20:34 -0400 Subject: Any PyQt developers here? In-Reply-To: <mailman.809.1666721042.20444.python-list@python.org> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <0E65B029-0D91-448D-B59D-E5F4EC9D21E9@barrys-emacs.org> <mailman.809.1666721042.20444.python-list@python.org> Message-ID: <6GW5L.450338$wLZ8.351551@fx18.iad> On 10/25/2022 2:03 PM, Barry Scott wrote: > There is an active PyQt mailing list that has lots of helpful and knowledgeable people on it. > > https://www.riverbankcomputing.com/mailman/listinfo/pyqt > > Barry Thanks. I'll send some questions their way, I'm sure. From f96.heydari at gmail.com Wed Oct 26 02:18:21 2022 From: f96.heydari at gmail.com (Fatemeh Heydari) Date: Tue, 25 Oct 2022 23:18:21 -0700 (PDT) Subject: score function in linear regression model In-Reply-To: <mailman.793.1666620829.20444.python-list@python.org> References: <20221024050644.zf3tlxrs3nofbe4r@feather> <0b2b86f6-2235-4996-83e3-0da69b3f3c76n@googlegroups.com> <mailman.793.1666620829.20444.python-list@python.org> Message-ID: <370c2c99-abb5-49a4-a9fc-9310343533b8n@googlegroups.com> On Monday, October 24, 2022 at 7:14:10 AM UTC-7, Reto wrote: > On Sun, Oct 23, 2022 at 05:11:10AM -0700, Fatemeh Heydari wrote: > > model.score(X,Y) > > That will basically check how good your model is. > > It takes a bunch of X values with known values, which you provide in Y > and compares the output of model.Predict(X) with the Y's and gives you > some metrics as to how good that performed. > > In the case of linear regression that be R^2, the coefficient of determination > of the prediction. > > Cheers, > Reto Dear Reto Thanks for your attention. But I calculated R^2 for the model with the code : r2_score(predictedY,Y) and I got different result from the "score " function. I wish to know what mathematical formulation is behind this function Thanks again From list1 at tompassin.net Wed Oct 26 13:44:55 2022 From: list1 at tompassin.net (Thomas Passin) Date: Wed, 26 Oct 2022 13:44:55 -0400 Subject: score function in linear regression model In-Reply-To: <370c2c99-abb5-49a4-a9fc-9310343533b8n@googlegroups.com> References: <20221024050644.zf3tlxrs3nofbe4r@feather> <0b2b86f6-2235-4996-83e3-0da69b3f3c76n@googlegroups.com> <mailman.793.1666620829.20444.python-list@python.org> <370c2c99-abb5-49a4-a9fc-9310343533b8n@googlegroups.com> Message-ID: <77fe86d4-fc0c-9766-36c8-b4b015763bc6@tompassin.net> There's a fairly good rundown of score() here: "[Python/Sklearn] How does .score() works?" https://www.kaggle.com/getting-started/27261 On 10/26/2022 2:18 AM, Fatemeh Heydari wrote: > On Monday, October 24, 2022 at 7:14:10 AM UTC-7, Reto wrote: >> On Sun, Oct 23, 2022 at 05:11:10AM -0700, Fatemeh Heydari wrote: >>> model.score(X,Y) >> >> That will basically check how good your model is. >> >> It takes a bunch of X values with known values, which you provide in Y >> and compares the output of model.Predict(X) with the Y's and gives you >> some metrics as to how good that performed. >> >> In the case of linear regression that be R^2, the coefficient of determination >> of the prediction. >> >> Cheers, >> Reto > > > Dear Reto > Thanks for your attention. But I calculated R^2 for the model with the code : r2_score(predictedY,Y) > and I got different result from the "score " function. I wish to know what mathematical formulation is behind this function > > Thanks again From Karsten.Hilbert at gmx.net Wed Oct 26 14:55:19 2022 From: Karsten.Hilbert at gmx.net (Karsten Hilbert) Date: Wed, 26 Oct 2022 20:55:19 +0200 Subject: "mailcap" to be removed (3.13) -- suggested replacement ? Message-ID: <Y1mCl25x8KCgZChS@hermes.hilbert.loc> Dear list, Python 3.11 marks "mailcap" for removal in 3.13. The documentation speaks about "mimetypes" being a replacement, of sorts. I agree with removing dead batteries. However, I can't really see how "mimetypes" helps in replacing the functionality of "mailcap" ? Put another way: what is the suggested way of replacing that module in existing code ? The use case is "find the viewer for any kind of file (by mimetype), as long as the system knows". Thanks, Karsten -- GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B From elasstiika at gmail.com Wed Oct 26 15:01:04 2022 From: elasstiika at gmail.com (elas tica) Date: Wed, 26 Oct 2022 12:01:04 -0700 (PDT) Subject: Operator: inappropriate wording? Message-ID: <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> Quotes from The Python Language Reference, Release 3.10.8: - Note that tuples are not formed by the parentheses, but rather by use of the comma operator (p. 66) - Note: If the object is a class instance and the attribute reference occurs on both sides of the assignment operator (p. 86) - The second half of the list, the augmented assignment operators, serve lexically as delimiters, but also perform an operation (p. 15) Do you agree with this use of the term "operator"? Because there is no such "comma operator" in Python as explained by the official FAQ: https://docs.python.org/3/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence And, =, += and the like are not operators since (a=b), (a+=b), etc have no value. There is no assignment operator instead there exists an assignment statement. The only assignment operator I can figure out is the walrus operator. To confirm, The Python Language Reference gives here: https://docs.python.org/3/reference/lexical_analysis.html#operators the set of tokens considered as operator and the =, += tokens are not listed whereas := is. From roel at roelschroeven.net Wed Oct 26 15:59:10 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Wed, 26 Oct 2022 21:59:10 +0200 Subject: Operator: inappropriate wording? In-Reply-To: <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> References: <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> Message-ID: <234a67cd-7b63-8793-ca2d-74d582d8e3ea@roelschroeven.net> elas tica schreef op 26/10/2022 om 21:01: > Quotes from The Python Language Reference, Release 3.10.8: > > - Note that tuples are not formed by the parentheses, but rather by use of the comma operator (p. 66) > - Note: If the object is a class instance and the attribute reference occurs on both sides of the assignment operator (p. 86) > - The second half of the list, the augmented assignment operators, serve lexically as delimiters, but also perform an operation (p. 15) > > > > Do you agree with this use of the term "operator"? It's a bit fuzzy, I guess. Comma, =, +=, *= etc. are in section 2.6 "Delimiters" and not in section 2.5 "Operators" of The Python Language Reference, which would seem to imply that those are not operators. But the text in section 2.6 then says "The second half of the list, the augmented assignment _operators_, serve lexically as delimiters, but also perform an operation.", so at least the augmented assignment operators are seen as operators despite not being in the Operators section. > Because there is no such "comma operator" in Python as explained by the official FAQ: https://docs.python.org/3/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence That does seem to contradict the text in the language reference. > And, =, += and the like are not operators since (a=b), (a+=b), etc have no value. There is no assignment operator instead there exists an assignment statement. The only assignment operator I can figure out is the walrus operator. I think that's a good point too. The language reference calls those things 'delimiters', which doesn't feel like a good description either for many of them. I find it weird to think of =, *+, +=as a delimiter. Maybe that's why those things are called operators anyway instead of delimiters in many places? Things like "Note: If the object is a class instance and the attribute reference occurs on both sides of the assignment _delimiter_" sound a bit weird I feel, even though completely correct according to the language reference. So yeah I think you have a point that the terminology regarding those tokens is not very consistent at the least. -- "Honest criticism is hard to take, particularly from a relative, a friend, an acquaintance, or a stranger." -- Franklin P. Jones From gweatherby at uchc.edu Wed Oct 26 16:10:37 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Wed, 26 Oct 2022 20:10:37 +0000 Subject: Operator: inappropriate wording? In-Reply-To: <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> References: <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> Message-ID: <SA1PR14MB585507DE975BB911C3EF165AB9309@SA1PR14MB5855.namprd14.prod.outlook.com> No. If the docs say in one place a comma is not an operator, they shouldn?t call it an operator in another place. I?ve submitted a pull request https://github.com/python/cpython/pull/98736 -- we?ll have to see what The Powers That Be think. From: Python-list <python-list-bounces+gweatherby=uchc.edu at python.org> on behalf of elas tica <elasstiika at gmail.com> Date: Wednesday, October 26, 2022 at 3:32 PM To: python-list at python.org <python-list at python.org> Subject: Operator: inappropriate wording? *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** Quotes from The Python Language Reference, Release 3.10.8: - Note that tuples are not formed by the parentheses, but rather by use of the comma operator (p. 66) - Note: If the object is a class instance and the attribute reference occurs on both sides of the assignment operator (p. 86) - The second half of the list, the augmented assignment operators, serve lexically as delimiters, but also perform an operation (p. 15) Do you agree with this use of the term "operator"? Because there is no such "comma operator" in Python as explained by the official FAQ: https://urldefense.com/v3/__https://docs.python.org/3/faq/programming.html*what-s-up-with-the-comma-operator-s-precedence__;Iw!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeWVu5edfg$<https://urldefense.com/v3/__https:/docs.python.org/3/faq/programming.html*what-s-up-with-the-comma-operator-s-precedence__;Iw!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeWVu5edfg$> And, =, += and the like are not operators since (a=b), (a+=b), etc have no value. There is no assignment operator instead there exists an assignment statement. The only assignment operator I can figure out is the walrus operator. To confirm, The Python Language Reference gives here: https://urldefense.com/v3/__https://docs.python.org/3/reference/lexical_analysis.html*operators__;Iw!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeVnKYO3BA$<https://urldefense.com/v3/__https:/docs.python.org/3/reference/lexical_analysis.html*operators__;Iw!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeVnKYO3BA$> the set of tokens considered as operator and the =, += tokens are not listed whereas := is. -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeW3iNHD7g$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nL9TZBaXZH87JOWNN7D_3E0ytfdXH8tkUxvTdF4dXbVqOJS0yF0C7idVg4ZGee7FiFyPQqqNRcNeVeW3iNHD7g$> From nospam at dfs.com Wed Oct 26 16:47:21 2022 From: nospam at dfs.com (DFS) Date: Wed, 26 Oct 2022 16:47:21 -0400 Subject: A little source file analyzer Message-ID: <q1h6L.457904$wLZ8.187228@fx18.iad> Nothing special, but kind of fun to use $python progname.py sourcefile.py --------------------------------------------------------- #count blank lines, comments, source code import sys #counters imports, blanks,comments, source = 0,0,0,0 functions, dbexec, total = 0,0,0 #python builtins builtins = 0 bins = ['abs','aiter','all','any','anext','ascii','bin','bool','breakpoint','bytearray','bytes','callable','chr','classmethod','compile','complex','delattr','dict','dir','divmod','enumerate','eval','exec','filter','float','format','frozenset','getattr','globals','hasattr','hash','help','hex','id','input','int','isinstance','issubclass','iter','len','list','locals','map','max','memoryview','min','next','object','oct','open','ord','pow','property','range','repr','reversed','round','set','setattr','slice','sorted','staticmethod','str','sum','super','tuple','type','vars','zip'] bins2,bins3 = [],[] for bi in bins: bins2.append(' ' + bi + '(') #look for leading space then builtin then open paren #todo use for source files other than .py ccomments = 0 py_comment = ['#','~','@'] c_comment = ['/*','//'] #read file f = open(sys.argv[1], encoding='utf-8') lines = f.read().splitlines() f.close() #print builtin usage count #def binusage(): #iterate file linenbr = 0 for line in lines: line = line.strip() linenbr += 1 if line == '' : blanks += 1 if line != '': if line[0:1] == '#' : comments += 1 if line[0:3] == '"""' : comments += 1 if line[-3:1] == '"""' : comments += 1 if line[0:1] not in ['#','"']: source += 1 if line[0:3] == 'def' and line[-2:] == '):' : functions += 1 if '.execute' in line : dbexec += 1 if 'commit()' in line : dbexec += 1 if 'import' in line : imports += 1 if 'print(' in line : bins3.append('print') for bi in bins2: #usage of a python builtin function if bi in line: bins3.append(bi[1:-1]) total += 1 #output print('imports : ' + str(imports)) print('source : ' + str(source)) print('-functions: ' + str(functions)) print('-db exec : ' + str(dbexec) + 'x') ctxt = '' x = [(i,bins3.count(i)) for i in sorted(set(bins3))] for bi,cnt in x: ctxt += bi + '('+ str(cnt) + '), ' print('-builtins : ' + str(len(bins3)) + 'x [' + ctxt[:-2] + ']') print('comments : ' + str(comments)) print('blanks : ' + str(blanks)) print('Total : ' + str(total)) --------------------------------------------------------- From nospam at dfs.com Thu Oct 27 11:15:58 2022 From: nospam at dfs.com (DFS) Date: Thu, 27 Oct 2022 11:15:58 -0400 Subject: Any PyQt developers here? In-Reply-To: <mailman.805.1666719919.20444.python-list@python.org> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> Message-ID: <Ogx6L.101819$chF5.43894@fx08.iad> On 10/25/2022 1:45 PM, Thomas Passin wrote: > On 10/25/2022 1:03 PM, DFS wrote: >> Having problems with removeRow() on a QTableView object. > > removeRow() isn't listed as being a method of a QTableView, not even an > inherited method, so how are you calling removeRow() on it? (See > https://doc.qt.io/qt-6/qtableview-members.html) Since you helped me on the last one, maybe you could try to answer a couple more [probably simple] roadblocks I'm hitting. I just wanna set the font to bold/not-bold when clicking on a row in QTableView. With a QTableWidget I do it like this: font = QFont() font.setBold(True) or False QTableWidget.item(row,col).setFont(font) But the QTableView has data/view 'models' attached to it and that syntax doesn't work: Tried: font = QFont() font.setBold(True) or False model = QTableView.model() model.setFont(model.index(row,col), font) Throws AttributeError: 'QSqlTableModel' object has no attribute 'setFont' This doesn't throw an error, but doesn't show bold: model.setData(model.index(tblRow, col), font, Qt.FontRole) Any ideas? Thanks From list1 at tompassin.net Thu Oct 27 15:47:49 2022 From: list1 at tompassin.net (Thomas Passin) Date: Thu, 27 Oct 2022 15:47:49 -0400 Subject: Any PyQt developers here? In-Reply-To: <Ogx6L.101819$chF5.43894@fx08.iad> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> <Ogx6L.101819$chF5.43894@fx08.iad> Message-ID: <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> On 10/27/2022 11:15 AM, DFS wrote: > On 10/25/2022 1:45 PM, Thomas Passin wrote: >> On 10/25/2022 1:03 PM, DFS wrote: >>> Having problems with removeRow() on a QTableView object. >> >> removeRow() isn't listed as being a method of a QTableView, not even >> an inherited method, so how are you calling removeRow() on it? (See >> https://doc.qt.io/qt-6/qtableview-members.html) > > Since you helped me on the last one, maybe you could try to answer a > couple more [probably simple] roadblocks I'm hitting. > > > I just wanna set the font to bold/not-bold when clicking on a row in > QTableView. > > > > With a QTableWidget I do it like this: > > font = QFont() > font.setBold(True) or False > QTableWidget.item(row,col).setFont(font) > > > > But the QTableView has data/view 'models' attached to it and that syntax > doesn't work: > > > Tried: > font = QFont() > font.setBold(True) or False > model = QTableView.model() > model.setFont(model.index(row,col), font) > > Throws AttributeError: 'QSqlTableModel' object has no attribute 'setFont' > > > This doesn't throw an error, but doesn't show bold: > model.setData(model.index(tblRow, col), font, Qt.FontRole) > > > Any ideas? You definitely need to be setting the font in an item. I'm not sure but I think that your QFont() doesn't have any properties, so it doesn't do anything. I found this bit in a page - it's in C++ instead of Python but that doesn't really make a difference except for the exact syntax to use - https://forum.qt.io/topic/70016/qlistview-item-font-stylesheet-not-working/4 QVariant v = ModelBaseClass::data(index,role); if( condition && role == Qt::FontRole ) { QFont font = v.value<QFont>(); font.setBold( true ); v = QVariant::fromValue<QFont>( font ); } IOW, you have to get the font from the item, then set it to bold, which you would do with setFont(). Then you set that new font on the item. Of course you would have to unset bold on it later. See https://doc.qt.io/qt-6/qtablewidgetitem.html#font Instead of "item", you might need to operate on "row". I didn't look into that. Since a row probably doesn't have just one font (since it can have more than one item), you'd still have to get the font from some item in the row. You might also be able to make the item bold using CSS, but I'm not sure. > Thanks Internet searches are your friend for questions like this. I've never worked with a QTableView, so I had to start with some knowledge about some other parts of QT. I found the first page searching for "qt set qtableview row font", and the second searching for "qtablewidgetitem". From PythonList at DancesWithMice.info Thu Oct 27 17:38:51 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 28 Oct 2022 10:38:51 +1300 Subject: Crafting Software (PUG practical meeting) Message-ID: <fd1b6fc6-4125-8d17-2b5b-b4e5a1330b83@DancesWithMice.info> Wed, 2 Nov 2022 at 1830~2030 NZDT (0530~0730 UTC) Come to our Coding Evening with your Python questions, suggestions, problems, etc; and/or bring a Lightning Talk about your current topic-of-interest - something new, a recent discovery, a contribution you have made... Thereafter, we will continue the Crafting Software series. These are code-along-at-home exercises. The initial sessions were designed for Beginners, and have gradually 'grown' into areas which will challenge and benefit Journeyman Python Programmers and even Masters. The aim is to complement our Software Craftsmanship Presentation series with practical coding and observing the advantages of craftsmanship, as we/the code becomes more sophisticated. We are enjoying meeting attendees from all over the world (Europeans invert their screens to be able to see us 'right way up' (!?)) Please RSVP to be advised of the web-conference URL, and QuickStart Guide. https://www.meetup.com/nzpug-auckland/events/hgxmwsydcpbdb/ -- Regards, =dn Auckland Branch, New Zealand Python Users' Group From list1 at tompassin.net Fri Oct 28 01:01:13 2022 From: list1 at tompassin.net (Thomas Passin) Date: Fri, 28 Oct 2022 01:01:13 -0400 Subject: Any PyQt developers here? In-Reply-To: <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> <Ogx6L.101819$chF5.43894@fx08.iad> <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> Message-ID: <24b0e4c2-3faf-c138-aade-89fa1b154847@tompassin.net> This looks like a useful tutorial - https://doc.qt.io/qt-6/modelview.html On 10/27/2022 3:47 PM, Thomas Passin wrote: > On 10/27/2022 11:15 AM, DFS wrote: >> On 10/25/2022 1:45 PM, Thomas Passin wrote: >>> On 10/25/2022 1:03 PM, DFS wrote: >>>> Having problems with removeRow() on a QTableView object. >>> >>> removeRow() isn't listed as being a method of a QTableView, not even >>> an inherited method, so how are you calling removeRow() on it? (See >>> https://doc.qt.io/qt-6/qtableview-members.html) >> >> Since you helped me on the last one, maybe you could try to answer a >> couple more [probably simple] roadblocks I'm hitting. >> >> >> I just wanna set the font to bold/not-bold when clicking on a row in >> QTableView. >> >> >> >> With a QTableWidget I do it like this: >> >> font = QFont() >> font.setBold(True) or False >> QTableWidget.item(row,col).setFont(font) >> >> >> >> But the QTableView has data/view 'models' attached to it and that >> syntax doesn't work: >> >> >> Tried: >> font = QFont() >> font.setBold(True) or False >> model = QTableView.model() >> model.setFont(model.index(row,col), font) >> >> Throws AttributeError: 'QSqlTableModel' object has no attribute 'setFont' >> >> >> This doesn't throw an error, but doesn't show bold: >> model.setData(model.index(tblRow, col), font, Qt.FontRole) >> >> >> Any ideas? > > You definitely need to be setting the font in an item.? I'm not sure but > I think that your QFont() doesn't have any properties, so it doesn't do > anything.? I found this bit in a page - it's in C++ instead of Python > but that doesn't really make a difference except for the exact syntax to > use - > > > https://forum.qt.io/topic/70016/qlistview-item-font-stylesheet-not-working/4 > > ????? QVariant v = ModelBaseClass::data(index,role); > ????? if( condition && role == Qt::FontRole ) > ????? { > ?????????????? QFont font = v.value<QFont>(); > ??????????????????? font.setBold( true ); > ?????????????? v = QVariant::fromValue<QFont>( font ); > ????? } > > IOW, you have to get the font from the item, then set it to bold, which > you would do with setFont().? Then you set that new font on the item. Of > course you would have to unset bold on it later. See > > https://doc.qt.io/qt-6/qtablewidgetitem.html#font > > Instead of "item", you might need to operate on "row".? I didn't look > into that.? Since a row probably doesn't have just one font (since it > can have more than one item), you'd still have to get the font from some > item in the row. > > You might also be able to make the item bold using CSS, but I'm not sure. > >> Thanks > > Internet searches are your friend for questions like this.? I've never > worked with a QTableView, so I had to start with some knowledge about > some other parts of QT.? I found the first page searching for "qt set > qtableview row font", and the second searching for "qtablewidgetitem". > From list1 at tompassin.net Fri Oct 28 22:56:10 2022 From: list1 at tompassin.net (Thomas Passin) Date: Fri, 28 Oct 2022 22:56:10 -0400 Subject: Any PyQt developers here? In-Reply-To: <24b0e4c2-3faf-c138-aade-89fa1b154847@tompassin.net> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> <Ogx6L.101819$chF5.43894@fx08.iad> <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> <24b0e4c2-3faf-c138-aade-89fa1b154847@tompassin.net> Message-ID: <84467aa2-5580-310a-a8f6-28b234429a6f@tompassin.net> On 10/28/2022 1:01 AM, Thomas Passin wrote: {snip] >> You might also be able to make the item bold using CSS, but I'm not sure. Apparently so: QTreeView::item:selected { background-color: #1d3dec; color: white; } See https://joekuan.wordpress.com/2015/10/02/styling-qt-qtreeview-with-css/. From nospam at dfs.com Fri Oct 28 23:31:48 2022 From: nospam at dfs.com (DFS) Date: Fri, 28 Oct 2022 23:31:48 -0400 Subject: Any PyQt developers here? In-Reply-To: <mailman.818.1666904853.20444.python-list@python.org> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> <Ogx6L.101819$chF5.43894@fx08.iad> <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> <mailman.818.1666904853.20444.python-list@python.org> Message-ID: <D817L.261631$BQA7.128173@fx41.iad> On 10/27/2022 3:47 PM, Thomas Passin wrote: > On 10/27/2022 11:15 AM, DFS wrote: >> On 10/25/2022 1:45 PM, Thomas Passin wrote: >>> On 10/25/2022 1:03 PM, DFS wrote: >>>> Having problems with removeRow() on a QTableView object. >>> >>> removeRow() isn't listed as being a method of a QTableView, not even >>> an inherited method, so how are you calling removeRow() on it? (See >>> https://doc.qt.io/qt-6/qtableview-members.html) >> >> Since you helped me on the last one, maybe you could try to answer a >> couple more [probably simple] roadblocks I'm hitting. >> >> >> I just wanna set the font to bold/not-bold when clicking on a row in >> QTableView. >> >> >> >> With a QTableWidget I do it like this: >> >> font = QFont() >> font.setBold(True) or False >> QTableWidget.item(row,col).setFont(font) >> >> >> >> But the QTableView has data/view 'models' attached to it and that >> syntax doesn't work: >> >> >> Tried: >> font = QFont() >> font.setBold(True) or False >> model = QTableView.model() >> model.setFont(model.index(row,col), font) >> >> Throws AttributeError: 'QSqlTableModel' object has no attribute 'setFont' >> >> >> This doesn't throw an error, but doesn't show bold: >> model.setData(model.index(tblRow, col), font, Qt.FontRole) >> >> >> Any ideas? > > You definitely need to be setting the font in an item.? I'm not sure but > I think that your QFont() doesn't have any properties, so it doesn't do > anything.? I found this bit in a page - it's in C++ instead of Python > but that doesn't really make a difference except for the exact syntax to > use - > > > https://forum.qt.io/topic/70016/qlistview-item-font-stylesheet-not-working/4 > > > ????? QVariant v = ModelBaseClass::data(index,role); > ????? if( condition && role == Qt::FontRole ) > ????? { > ?????????????? QFont font = v.value<QFont>(); > ??????????????????? font.setBold( true ); > ?????????????? v = QVariant::fromValue<QFont>( font ); > ????? } > > IOW, you have to get the font from the item, then set it to bold, which > you would do with setFont().? Then you set that new font on the item. Of > course you would have to unset bold on it later. See > > https://doc.qt.io/qt-6/qtablewidgetitem.html#font > > Instead of "item", you might need to operate on "row".? I didn't look > into that.? Since a row probably doesn't have just one font (since it > can have more than one item), you'd still have to get the font from some > item in the row. > > You might also be able to make the item bold using CSS, but I'm not sure. > >> Thanks > > Internet searches are your friend for questions like this. Before I posted I spent a couple hours looking online, reading the docs, and trying different ways. I found one person that said they did it but their syntax didn't work. But it doesn't throw an error either. model.setData(model.index(tblRow, col), font, Qt.FontRole) When I'm done with my app (nearly 2K LOC) I'm going to put a summary out there somewhere with a bunch of examples of easy ways to do things. For one thing I wrote zero classes. Not one. > I've never > worked with a QTableView, so I had to start with some knowledge about > some other parts of QT.? I found the first page searching for "qt set > qtableview row font", and the second searching for "qtablewidgetitem". I used TableWidgets in 2 apps and no problems. In this app there's more data and more sorting, and one of the TableWidgets took a while to load 35K rows (7 items per row). So I tried a TableView. Incredibly fast - 4x the speed - but it doesn't have the bolding in place yet. That could slow it down. As you know, a TableView is tied to the underlying datasource (in my case via a QSqlTableModel), but it's much faster to show data than a TableWidget, because with the widget you have populate each cell with setItem(). The Widget is slower but easier to work with. So it's a tradeoff. And I think I found some bugs in the TableViews. The Views have editStrategies() that control how data is updated (if the model supports editing), but they don't work the way the docs say they do. In my app, when I click on a row a flag field is changed from N to Y onscreen (well, it's hidden but it's in the row). model.setData(model.index(row,7), 'Y') OnFieldChange : all changes to the model will be applied immediately to the database. model.setEditStrategy(QSqlTableModel.OnFieldChange) Doesn't work right. The screen is updated the first row you click on, but the db isn't updated until you reload the view. OnRowChange : changes to a row will be applied when the user selects a different row. model.setEditStrategy(QSqlTableModel.OnRowChange) Doesn't work right. The screen is updated the first row you click on, but the db isn't updated until you reload the view. OnManualSubmit : all changes will be cached in the model until either submitAll() or revertAll() is called. model.setEditStrategy(QSqlTableModel.OnManualSubmit) This works the best: the screen changes on each row I click, but the db isn't updated even if I do submitAll() right after setData(). Have to reload the view for the changes to propagate to the db. Since none work as they say, the issue is probably on my end. Don't know. I just ended up issuing a quick SQL UPDATE statement for the row. If you really want speed use the read-only QSqlQueryModel(). Loads 35K rows to screen in 1/2 a second (but no bolding applied - I really have to figure that out, as it's a central feature of the GUI) Thanks for your help. From torriem at gmail.com Sat Oct 29 11:03:28 2022 From: torriem at gmail.com (Michael Torrie) Date: Sat, 29 Oct 2022 09:03:28 -0600 Subject: Any PyQt developers here? In-Reply-To: <D817L.261631$BQA7.128173@fx41.iad> References: <1GU5L.400518$9Yp5.247552@fx12.iad> <c6a527cc-18ba-58e0-5525-95f3a5f34ac3@tompassin.net> <mailman.805.1666719919.20444.python-list@python.org> <Ogx6L.101819$chF5.43894@fx08.iad> <c1e1cc2a-6852-af2f-da1c-60d30ff373cd@tompassin.net> <mailman.818.1666904853.20444.python-list@python.org> <D817L.261631$BQA7.128173@fx41.iad> Message-ID: <b1e4a776-adec-72ca-c56e-926164b51d77@gmail.com> On 10/28/22 21:31, DFS wrote: > I found one person that said they did it but their syntax didn't work. > But it doesn't throw an error either. > > model.setData(model.index(tblRow, col), font, Qt.FontRole) I wouldn't expect that to work but it's understandable why it didn't throw an error. setData() is used to edit the contents of the model at the provided index. Remember a model can store anything. All this does is replace whatever was at that index with a Font object instance. I'm puzzled why you keep trying to mess with the model when it's the view that does the actual font setting. Remember that a single model can be used with more than one view at the same time, each view implementing its own style. Thus a model has no information like fonts in it, nor should it, other than perhaps HTML text markup that the view will render. Did you consult the folk on the PyQt mailing list? Or even the main Qt lists? This isn't language-specific stuff you're asking about. From python at bernardledru.be Sat Oct 29 14:21:46 2022 From: python at bernardledru.be (Bernard LEDRU) Date: Sat, 29 Oct 2022 20:21:46 +0200 Subject: str.replace() when str contains \ Message-ID: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> Hello, https://docs.python.org/3/library/stdtypes.html#string-methods str.replace(old, new[, count])? Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. Attention when the string contains the escape character. Consider : >>> a="H:\2023"; print(a.replace("\\","/")) H:3 >>> a="H:\a2023"; print(a.replace("\\","/")) H:2023 >>> a="H:\_2023"; print(a.replace("\\","/")) H:/_2023 Best regards, Bernard LEDRU From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sat Oct 29 13:45:16 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sat, 29 Oct 2022 18:45:16 +0100 Subject: A typing question Message-ID: <tjjorc$dc7$1@gioia.aioe.org> Hi! Consider this simple script ... ___________________ from typing import List, Optional class GLOBALS: foos=None class Foo: def __init__(self): pass class Foos: Foos: List[Foo]=[] # SOME GLOBALS ARE USED HERE in a real script def __init__(self): pass GLOBALS.foos: Optional[Foos]=Foos() ___________________ Running mypy on it: pt9.py:18: error: Type cannot be declared in assignment to non-self attribute pt9.py:18: error: Incompatible types in assignment (expression has type "Foos", variable has type "None") Line 18 is last line and pt9.py is the scrip. Replacing last line by GLOBALS.foos=Foos() and running mypy still gives the second error. pt9.py:18: error: Incompatible types in assignment (expression has type "Foos", variable has type "None") What is the common practice in these cases? Thank you. From sam.z.ezeh at gmail.com Sat Oct 29 17:23:11 2022 From: sam.z.ezeh at gmail.com (Sam Ezeh) Date: Sat, 29 Oct 2022 22:23:11 +0100 Subject: Fwd: A typing question In-Reply-To: <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> Message-ID: <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> Do you want the following? ``` from typing import List, Optional class GLOBALS: foos: Optional[Foos] = None class Foo: def __init__(self): pass class Foos: Foos: List[Foo] = [] def __init__(self): pass GLOBALS.foos = Foos() ``` Kind regards, Sam Ezeh On Sat, 29 Oct 2022 at 22:13, Paulo da Silva < p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > Hi! > > Consider this simple script ... > > ___________________ > from typing import List, Optional > > class GLOBALS: > foos=None > > class Foo: > > def __init__(self): > pass > > class Foos: > Foos: List[Foo]=[] > # SOME GLOBALS ARE USED HERE in a real script > > def __init__(self): > pass > > GLOBALS.foos: Optional[Foos]=Foos() > ___________________ > > Running mypy on it: > pt9.py:18: error: Type cannot be declared in assignment to non-self > attribute > pt9.py:18: error: Incompatible types in assignment (expression has type > "Foos", variable has type "None") > Line 18 is last line and pt9.py is the scrip. > > Replacing last line by > GLOBALS.foos=Foos() > and running mypy still gives the second error. > pt9.py:18: error: Incompatible types in assignment (expression has type > "Foos", variable has type "None") > > What is the common practice in these cases? > > Thank you. > > -- > https://mail.python.org/mailman/listinfo/python-list > From barry at barrys-emacs.org Sat Oct 29 17:27:38 2022 From: barry at barrys-emacs.org (Barry) Date: Sat, 29 Oct 2022 22:27:38 +0100 Subject: str.replace() when str contains \ In-Reply-To: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> References: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> Message-ID: <F48D0C9B-8880-4896-ABB9-A471B2D25B89@barrys-emacs.org> > On 29 Oct 2022, at 22:14, Bernard LEDRU <python at bernardledru.be> wrote: > > ?Hello, > > https://docs.python.org/3/library/stdtypes.html#string-methods > > str.replace(old, new[, count])? > Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. > > Attention when the string contains the escape character. > > Consider : > >>>> a="H:\2023"; print(a.replace("\\","/")) > H:3 >>>> a="H:\a2023"; print(a.replace("\\","/")) > H:2023 >>>> a="H:\_2023"; print(a.replace("\\","/")) > H:/_2023 String a does not quote the \ after :. You need ?H:\\2023? etc. check what a is before the replace with a print(repr(a)) Barry > > Best regards, > Bernard LEDRU > -- > https://mail.python.org/mailman/listinfo/python-list From PythonList at DancesWithMice.info Sat Oct 29 17:34:47 2022 From: PythonList at DancesWithMice.info (dn) Date: Sun, 30 Oct 2022 10:34:47 +1300 Subject: Fwd: A typing question In-Reply-To: <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> Message-ID: <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the original: GLOBALS.foos: Optional[Foos]=Foos() but not the fall-back: GLOBALS.foos=Foos() Must admit, the first query coming to mind was: why is the typing taking place at initialisation-time, rather than within the (class) definition? At definition time "foos" has already been typed as None by implication! Solution (below) will not work if the mention of Foos in GLOBALS is a forward-reference. Either move GLOBALS to suit, or surround "Foos" with quotes. Also, these days (Python version allowing) importing "List" is unnecessary. Instead could use "list". On 30/10/2022 10.23, Sam Ezeh wrote: > Do you want the following? > > ``` > from typing import List, Optional > > > class GLOBALS: > foos: Optional[Foos] = None > > > class Foo: > def __init__(self): > pass > > > class Foos: > Foos: List[Foo] = [] > > def __init__(self): > pass > > > GLOBALS.foos = Foos() > ``` > > Kind regards, > Sam Ezeh > > On Sat, 29 Oct 2022 at 22:13, Paulo da Silva < > p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: > >> Hi! >> >> Consider this simple script ... >> >> ___________________ >> from typing import List, Optional >> >> class GLOBALS: >> foos=None >> >> class Foo: >> >> def __init__(self): >> pass >> >> class Foos: >> Foos: List[Foo]=[] >> # SOME GLOBALS ARE USED HERE in a real script >> >> def __init__(self): >> pass >> >> GLOBALS.foos: Optional[Foos]=Foos() >> ___________________ >> >> Running mypy on it: >> pt9.py:18: error: Type cannot be declared in assignment to non-self >> attribute >> pt9.py:18: error: Incompatible types in assignment (expression has type >> "Foos", variable has type "None") >> Line 18 is last line and pt9.py is the scrip. >> >> Replacing last line by >> GLOBALS.foos=Foos() >> and running mypy still gives the second error. >> pt9.py:18: error: Incompatible types in assignment (expression has type >> "Foos", variable has type "None") >> >> What is the common practice in these cases? >> >> Thank you. >> >> -- >> https://mail.python.org/mailman/listinfo/python-list >> -- Regards, =dn From list1 at tompassin.net Sat Oct 29 18:14:49 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sat, 29 Oct 2022 18:14:49 -0400 Subject: str.replace() when str contains \ In-Reply-To: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> References: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> Message-ID: <ffb9bf30-a4d6-ca09-0dc2-e8d9b1502feb@tompassin.net> Better to use raw strings whenever backslashes are involved. On 10/29/2022 2:21 PM, Bernard LEDRU wrote: > Hello, > > https://docs.python.org/3/library/stdtypes.html#string-methods > > str.replace(old, new[, count])? > Return a copy of the string with all occurrences of substring old > replaced by new. If the optional argument count is given, only the first > count occurrences are replaced. > > Attention when the string contains the escape character. > > Consider : > >>>> a="H:\2023"; print(a.replace("\\","/")) > H:3 >>>> a="H:\a2023"; print(a.replace("\\","/")) > H:2023 These examples actually produce an "H" with a symbol after it, a different symbol for each. Probably the message posting system can't display it, but I see it in a python terminal session on Windows. So the first a="H:\2023" example produces "Hx", where x is some symbol. Since there is no backslash, no character gets replaced. IOW, a="H:\2023"; print(a) and a="H:\2023"; print(a.replace("\\","/")) print the same thing. >>>> a="H:\_2023"; print(a.replace("\\","/")) > H:/_2023 What did you expect or want to happen? From drsalists at gmail.com Sat Oct 29 19:06:51 2022 From: drsalists at gmail.com (Dan Stromberg) Date: Sat, 29 Oct 2022 16:06:51 -0700 Subject: str.replace() when str contains \ In-Reply-To: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> References: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> Message-ID: <CAGGBd_pFb58wS8ufAQwU77ETwPuESaAR6eVvvhT5_MrjoOr7ug@mail.gmail.com> I believe you would do well to print a, before trying to transform it into something else. '\2' is chr(2). '\a' is the bell character, and is unprintable. '\_' is two characters though. On Sat, Oct 29, 2022 at 2:12 PM Bernard LEDRU <python at bernardledru.be> wrote: > Hello, > > https://docs.python.org/3/library/stdtypes.html#string-methods > > str.replace(old, new[, count])? > Return a copy of the string with all occurrences of substring old > replaced by new. If the optional argument count is given, only the first > count occurrences are replaced. > > Attention when the string contains the escape character. > > Consider : > > >>> a="H:\2023"; print(a.replace("\\","/")) > H:3 > >>> a="H:\a2023"; print(a.replace("\\","/")) > H:2023 > >>> a="H:\_2023"; print(a.replace("\\","/")) > H:/_2023 > > Best regards, > Bernard LEDRU > -- > https://mail.python.org/mailman/listinfo/python-list > From python at mrabarnett.plus.com Sat Oct 29 20:25:32 2022 From: python at mrabarnett.plus.com (MRAB) Date: Sun, 30 Oct 2022 01:25:32 +0100 Subject: str.replace() when str contains \ In-Reply-To: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> References: <74734ce6c4b19d8ad3bed4317b28da49@bernardledru.be> Message-ID: <b5ff8297-81ec-1e37-0756-950050e58b7f@mrabarnett.plus.com> On 2022-10-29 19:21, Bernard LEDRU wrote: > Hello, > > https://docs.python.org/3/library/stdtypes.html#string-methods > > str.replace(old, new[, count])? > Return a copy of the string with all occurrences of substring old > replaced by new. If the optional argument count is given, only the first > count occurrences are replaced. > > Attention when the string contains the escape character. > > Consider : > >>>> a="H:\2023"; print(a.replace("\\","/")) > H:3 >>>> a="H:\a2023"; print(a.replace("\\","/")) > H:2023 >>>> a="H:\_2023"; print(a.replace("\\","/")) > H:/_2023 > In a plain string literal, \ followed by 1..3 of the digits 0..7 is an octal (base 8) escape sequence, and \ followed by 'a' is the bel character, so '\7' == '\07' == '\007' == '\a' == '\x07'. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sat Oct 29 18:59:44 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sat, 29 Oct 2022 23:59:44 +0100 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> Message-ID: <tjkb91$1mid$1@gioia.aioe.org> ?s 22:34 de 29/10/22, dn escreveu: > Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the > original: > > ??? GLOBALS.foos: Optional[Foos]=Foos() > > but not the fall-back: > > ??? GLOBALS.foos=Foos() > > > Must admit, the first query coming to mind was: why is the typing taking > place at initialisation-time, rather than within the (class) definition? > At definition time "foos" has already been typed as None by implication! > > > Solution (below) will not work if the mention of Foos in GLOBALS is a > forward-reference. Either move GLOBALS to suit, or surround "Foos" with > quotes. This is the problem for me. So far, without typing, I used to have some config and globals classes, mostly to just group definitions an make the program more readable. A matter of taste and style. Now, "typing" is breaking this, mostly because of this forward reference issue. The funny thing is that if I replace foos by Foos it works because it gets known by the initial initialization :-) ! ________________________ from typing import List, Optional class GLOBALS: Foos: Optional[Foos]=None class Foo: def __init__(self): pass class Foos: Foos: List[Foo]=[] # SOME GLOBALS ARE USED HERE def __init__(self): pass GLOBALS.Foos=Foos() ________________________ > > > Also, these days (Python version allowing) importing "List" is > unnecessary. Instead could use "list". > > > > On 30/10/2022 10.23, Sam Ezeh wrote: >> Do you want the following? >> >> ``` >> from typing import List, Optional >> >> >> class GLOBALS: >> ???? foos: Optional[Foos] = None >> >> >> class Foo: >> ???? def __init__(self): >> ???????? pass >> >> >> class Foos: >> ???? Foos: List[Foo] = [] >> >> ???? def __init__(self): >> ???????? pass >> >> >> GLOBALS.foos = Foos() >> ``` >> >> Kind regards, >> Sam Ezeh >> >> On Sat, 29 Oct 2022 at 22:13, Paulo da Silva < >> p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> wrote: >> >>> Hi! >>> >>> Consider this simple script ... >>> >>> ___________________ >>> from typing import List, Optional >>> >>> class GLOBALS: >>> ????? foos=None >>> >>> class Foo: >>> >>> ????? def __init__(self): >>> ????????? pass >>> >>> class Foos: >>> ????? Foos: List[Foo]=[] >>> ????? # SOME GLOBALS ARE USED HERE in a real script >>> >>> ????? def __init__(self): >>> ????????? pass >>> >>> GLOBALS.foos: Optional[Foos]=Foos() >>> ___________________ >>> >>> Running mypy on it: >>> pt9.py:18: error: Type cannot be declared in assignment to non-self >>> attribute >>> pt9.py:18: error: Incompatible types in assignment (expression has type >>> "Foos", variable has type "None") >>> Line? 18 is last line and pt9.py is the scrip. >>> >>> Replacing last line by >>> GLOBALS.foos=Foos() >>> and running mypy still gives the second error. >>> pt9.py:18: error: Incompatible types in assignment (expression has type >>> "Foos", variable has type "None") >>> >>> What is the common practice in these cases? >>> >>> Thank you. >>> >>> -- >>> https://mail.python.org/mailman/listinfo/python-list >>> > From list1 at tompassin.net Sat Oct 29 20:14:12 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sat, 29 Oct 2022 20:14:12 -0400 Subject: A typing question In-Reply-To: <tjjorc$dc7$1@gioia.aioe.org> References: <tjjorc$dc7$1@gioia.aioe.org> Message-ID: <e15b0089-bbd9-03b9-993c-81b2c31b4ede@tompassin.net> On 10/29/2022 1:45 PM, Paulo da Silva wrote: > Hi! > > Consider this simple script ... > > ___________________ > from typing import List, Optional > > class GLOBALS: > ??? foos=None > > class Foo: > > ??? def __init__(self): > ??????? pass > > class Foos: > ??? Foos: List[Foo]=[] > ??? # SOME GLOBALS ARE USED HERE in a real script > > ??? def __init__(self): > ??????? pass > > GLOBALS.foos: Optional[Foos]=Foos() > ___________________ > > Running mypy on it: > pt9.py:18: error: Type cannot be declared in assignment to non-self > attribute > pt9.py:18: error: Incompatible types in assignment (expression has type > "Foos", variable has type "None") > Line? 18 is last line and pt9.py is the scrip. > > Replacing last line by > GLOBALS.foos=Foos() > and running mypy still gives the second error. > pt9.py:18: error: Incompatible types in assignment (expression has type > "Foos", variable has type "None") > > What is the common practice in these cases? > > Thank you. > I don't understand class Foos: Foos: List[Foo]=[] If "Foos" is supposed to be a class attribute, then it cannot have the same name as the class. Perhaps you meant the class to be named "Foo". Then a class attribute of Foos: List[Foo]=[] might barely make sense. Even then, remember that each instance of Foo would only know about the same (originally empty) list Foos. Is that really what you want? From PythonList at DancesWithMice.info Sat Oct 29 22:32:45 2022 From: PythonList at DancesWithMice.info (dn) Date: Sun, 30 Oct 2022 15:32:45 +1300 Subject: Fwd: A typing question In-Reply-To: <tjkb91$1mid$1@gioia.aioe.org> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> Message-ID: <ff63879c-2079-cfe0-4a61-1b9372f25dac@DancesWithMice.info> On 30/10/2022 11.59, Paulo da Silva wrote: >> Solution (below) will not work if the mention of Foos in GLOBALS is a >> forward-reference. Either move GLOBALS to suit, or surround "Foos" >> with quotes. > This is the problem for me. So far, without typing, I used to have some > config and globals classes, mostly to just group definitions an make the > program more readable. A matter of taste and style. Agreed, a good practice. > Now, "typing" is breaking this, mostly because of this forward reference > issue. As a first step, use the quotation-marks to indicate that such will be defined later in the code:- > class GLOBALS: > Foos: Optional[Foos]=None class GLOBALS: Foos: Optional["Foos"]=None Later, as gather (typing) expertise, can become more sophisticated, as-and-when... > The funny thing is that if I replace foos by Foos it works because it > gets known by the initial initialization :-) ! Is the objective to write (good) code, or merely to satisfy the type-checker? Something that is misleading is not going to be appreciated by others (including the +6-months you), eg a = a + 1 # decrement total Typing is not compulsory, and has been designed so that we can implement it a bit at a time, eg only one function amongst many contained by a module - if that's the only code that requires maintenance/update. Best not to create "technical debt" though! -- Regards, =dn From hjp-python at hjp.at Sun Oct 30 06:14:20 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 30 Oct 2022 11:14:20 +0100 Subject: A typing question In-Reply-To: <e15b0089-bbd9-03b9-993c-81b2c31b4ede@tompassin.net> References: <tjjorc$dc7$1@gioia.aioe.org> <e15b0089-bbd9-03b9-993c-81b2c31b4ede@tompassin.net> Message-ID: <20221030101420.vb7mi5lguwjymp3c@hjp.at> On 2022-10-29 20:14:12 -0400, Thomas Passin wrote: > I don't understand > > class Foos: > Foos: List[Foo]=[] > > If "Foos" is supposed to be a class attribute, then it cannot have the same > name as the class. Why not? They are in different namespaces. #v+ #!/usr/bin/python3 class Foos: Foos = [1, 2, 3] f = Foos() print(f.Foos) #v- This works and I see no reason why it shouldn't work. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221030/70497d4c/attachment.sig> From hjp-python at hjp.at Sun Oct 30 06:26:56 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 30 Oct 2022 11:26:56 +0100 Subject: Fwd: A typing question In-Reply-To: <tjkb91$1mid$1@gioia.aioe.org> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> Message-ID: <20221030102656.jwpzorowcuqnirlt@hjp.at> On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: > ?s 22:34 de 29/10/22, dn escreveu: > > Solution (below) will not work if the mention of Foos in GLOBALS is a > > forward-reference. > > Either move GLOBALS to suit, or surround "Foos" with quotes. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > This is the problem for me. Quotes are a bit ugly, but why are they a problem? [...] > The funny thing is that if I replace foos by Foos it works because it gets > known by the initial initialization :-) ! > > ________________________ > from typing import List, Optional > > class GLOBALS: > Foos: Optional[Foos]=None [...] > class Foos: That seems like a bug to me. What is the ?Foos? in ?Optional[Foos]? referring to? If it's the class attribute ?Foos? then that's not a type and even if its type is inferred that's not the same as ?Optional[it's type]?, or is it? If it's referring to the global symbol ?Foos? (i.e. the class defined later) that hasn't been defined yet, so it shouldn't work (or alternatively, if forward references are allowed it should always work). hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221030/20db3a9b/attachment.sig> From list1 at tompassin.net Sun Oct 30 09:23:27 2022 From: list1 at tompassin.net (Thomas Passin) Date: Sun, 30 Oct 2022 09:23:27 -0400 Subject: Fwd: A typing question In-Reply-To: <20221030102656.jwpzorowcuqnirlt@hjp.at> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> Message-ID: <557d6b4c-c5f7-f2f0-8bc7-5582ebfbac47@tompassin.net> On 10/30/2022 6:26 AM, Peter J. Holzer wrote: > On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: >> ?s 22:34 de 29/10/22, dn escreveu: >>> Solution (below) will not work if the mention of Foos in GLOBALS is a >>> forward-reference. >>> Either move GLOBALS to suit, or surround "Foos" with quotes. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >> This is the problem for me. > > Quotes are a bit ugly, but why are they a problem? > > [...] > >> The funny thing is that if I replace foos by Foos it works because it gets >> known by the initial initialization :-) ! >> >> ________________________ >> from typing import List, Optional >> >> class GLOBALS: >> Foos: Optional[Foos]=None > [...] >> class Foos: > > That seems like a bug to me. What is the ?Foos? in ?Optional[Foos]? > referring to? > > If it's the class attribute ?Foos? then that's not a type and even if > its type is inferred that's not the same as ?Optional[it's type]?, or is > it? > > If it's referring to the global symbol ?Foos? (i.e. the class defined > later) that hasn't been defined yet, so it shouldn't work (or > alternatively, if forward references are allowed it should always work). Quoting a forward-referenced type is the way to use one. Unquoted types need to have been declared already. From hjp-python at hjp.at Sun Oct 30 09:37:29 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Sun, 30 Oct 2022 14:37:29 +0100 Subject: Fwd: A typing question In-Reply-To: <557d6b4c-c5f7-f2f0-8bc7-5582ebfbac47@tompassin.net> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <557d6b4c-c5f7-f2f0-8bc7-5582ebfbac47@tompassin.net> Message-ID: <20221030133729.3rls5molew7eya5n@hjp.at> On 2022-10-30 09:23:27 -0400, Thomas Passin wrote: > On 10/30/2022 6:26 AM, Peter J. Holzer wrote: > > On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: > > > The funny thing is that if I replace foos by Foos it works because it gets > > > known by the initial initialization :-) ! > > > > > > ________________________ > > > from typing import List, Optional > > > > > > class GLOBALS: > > > Foos: Optional[Foos]=None > > [...] > > > class Foos: > > > > That seems like a bug to me. What is the ?Foos? in ?Optional[Foos]? > > referring to? > > > > If it's the class attribute ?Foos? then that's not a type and even if > > its type is inferred that's not the same as ?Optional[it's type]?, or is > > it? > > > > If it's referring to the global symbol ?Foos? (i.e. the class defined > > later) that hasn't been defined yet, so it shouldn't work (or > > alternatively, if forward references are allowed it should always work). > > Quoting a forward-referenced type is the way to use one. Unquoted types > need to have been declared already. Yes. I was referring to the code as written. Why does that work? I don't think it should. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221030/0647ccaa/attachment.sig> From __peter__ at web.de Sun Oct 30 15:43:23 2022 From: __peter__ at web.de (Peter Otten) Date: Sun, 30 Oct 2022 20:43:23 +0100 Subject: Fwd: A typing question In-Reply-To: <20221030133729.3rls5molew7eya5n@hjp.at> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <557d6b4c-c5f7-f2f0-8bc7-5582ebfbac47@tompassin.net> <20221030133729.3rls5molew7eya5n@hjp.at> Message-ID: <f26d3410-f4dc-095a-33b5-28c7a9cc43db@web.de> On 30/10/2022 14:37, Peter J. Holzer wrote: > On 2022-10-30 09:23:27 -0400, Thomas Passin wrote: >> On 10/30/2022 6:26 AM, Peter J. Holzer wrote: >>> On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: >>>> The funny thing is that if I replace foos by Foos it works because it gets >>>> known by the initial initialization :-) ! >>>> >>>> ________________________ >>>> from typing import List, Optional >>>> >>>> class GLOBALS: >>>> Foos: Optional[Foos]=None >>> [...] >>>> class Foos: >>> >>> That seems like a bug to me. What is the ?Foos? in ?Optional[Foos]? >>> referring to? >>> >>> If it's the class attribute ?Foos? then that's not a type and even if >>> its type is inferred that's not the same as ?Optional[it's type]?, or is >>> it? >>> >>> If it's referring to the global symbol ?Foos? (i.e. the class defined >>> later) that hasn't been defined yet, so it shouldn't work (or >>> alternatively, if forward references are allowed it should always work). >> >> Quoting a forward-referenced type is the way to use one. Unquoted types >> need to have been declared already. > > Yes. I was referring to the code as written. Why does that work? I don't > think it should. For me it makes sense. I think mypy should refrain from trying to figure out order of execution. If the above is disallowed, how about if random.randrange(2): class A: pass class B(A): pass ? One interesting consequence of that policy -- take the whole scope instead of the most recent appearance of a name is that class A: pass class A: pass won't compile. While I didn't expect that I think I like it ;) From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 30 00:10:54 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 30 Oct 2022 04:10:54 +0000 Subject: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <e15b0089-bbd9-03b9-993c-81b2c31b4ede@tompassin.net> <mailman.830.1667089953.20444.python-list@python.org> Message-ID: <tjktgf$jv9$1@gioia.aioe.org> ?s 01:14 de 30/10/22, Thomas Passin escreveu: > On 10/29/2022 1:45 PM, Paulo da Silva wrote: >> Hi! >> >> Consider this simple script ... >> >> ___________________ >> from typing import List, Optional >> >> class GLOBALS: >> ???? foos=None >> >> class Foo: >> >> ???? def __init__(self): >> ???????? pass >> >> class Foos: >> ???? Foos: List[Foo]=[] >> ???? # SOME GLOBALS ARE USED HERE in a real script >> >> ???? def __init__(self): >> ???????? pass >> >> GLOBALS.foos: Optional[Foos]=Foos() >> ___________________ >> >> Running mypy on it: >> pt9.py:18: error: Type cannot be declared in assignment to non-self >> attribute >> pt9.py:18: error: Incompatible types in assignment (expression has >> type "Foos", variable has type "None") >> Line? 18 is last line and pt9.py is the scrip. >> >> Replacing last line by >> GLOBALS.foos=Foos() >> and running mypy still gives the second error. >> pt9.py:18: error: Incompatible types in assignment (expression has >> type "Foos", variable has type "None") >> >> What is the common practice in these cases? >> >> Thank you. >> > > I don't understand > > class Foos: > ???? Foos: List[Foo]=[] > > If "Foos" is supposed to be a class attribute, then it cannot have the > same name as the class. Yes it can. You can refer it anywhere by Foos.Foos as a list of Foo elements. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 30 00:48:12 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 30 Oct 2022 04:48:12 +0000 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <ff63879c-2079-cfe0-4a61-1b9372f25dac@DancesWithMice.info> <mailman.831.1667097177.20444.python-list@python.org> Message-ID: <tjkvmc$14t5$1@gioia.aioe.org> ?s 02:32 de 30/10/22, dn escreveu: > On 30/10/2022 11.59, Paulo da Silva wrote: >>> Solution (below) will not work if the mention of Foos in GLOBALS is a >>> forward-reference. Either move GLOBALS to suit, or surround "Foos" >>> with quotes. >> This is the problem for me. So far, without typing, I used to have >> some config and globals classes, mostly to just group definitions an >> make the program more readable. A matter of taste and style. > > Agreed, a good practice. Thank you. > > >> Now, "typing" is breaking this, mostly because of this forward >> reference issue. > > As a first step, use the quotation-marks to indicate that such will be > defined later in the code:- > >> class GLOBALS: >> ??? Foos: Optional[Foos]=None > > class GLOBALS: > ??? Foos: Optional["Foos"]=None > > > Later, as gather (typing) expertise, can become more sophisticated, > as-and-when... > > >> The funny thing is that if I replace foos by Foos it works because it >> gets known by the initial initialization :-) ! > > Is the objective to write (good) code, or merely to satisfy the > type-checker? > > Something that is misleading is not going to be appreciated by others > (including the +6-months you), eg > > a = a + 1?? # decrement total > > Typing is not compulsory, and has been designed so that we can implement > it a bit at a time, eg only one function amongst many contained by a > module - if that's the only code that requires maintenance/update. > > Best not to create "technical debt" though! > The main idea is to eventually catch some, otherwise "hidden", errors and produce better and cleaner code. Documentation is also a must. Regards From jshem at yaxenu.org Sun Oct 30 10:01:15 2022 From: jshem at yaxenu.org (Julieta Shem) Date: Sun, 30 Oct 2022 11:01:15 -0300 Subject: an oop question Message-ID: <86y1sxmmvo.fsf@yaxenu.org> I have a question about a particular case I'm working on. I'm studying OOP. To ask the question, I'm going to have to introduce you my context here, so you'll need to bear with me. If you'd like to see the question right away, go to the section ``My difficulty in encapsulating a union''. (*) Introduction I wrote the classes class Empty: ... class Pair: ... With them, I can (sort of) make a union of them and build a Lisp-like list by defining that my Lisp-like list is either Empty or a Pair. For instance, here's a Lisp-like sequence that represents the string "abc". >>> Pair.fromIterable("abc") Pair('a', Pair('b', Pair('c', Empty()))) So far so good. (``Full'' code at the end of this message, if you'd like to more carefully look into my reasoning there.) (*) How to build a stack? These Lisp-like sequences are clearly a stack. You pop an element from it by grabbing the first element. You push an element on to it by just pairing the new element with the current stack. For instance, let's pop the 1-string "a" off of the stack. >>> ls = Pair.fromIterable("abc") >>> ls.first 'a' >>> ls = ls.rest >>> ls Pair('b', Pair('c', Empty())) Done. Let's push it back on. >>> ls = Pair("a", ls) >>> ls Pair('a', Pair('b', Pair('c', Empty()))) So far so good, but when it comes to building a better user interface for it I have no idea how to do it. I think one of the purposes of OOP is to organize code hierarchically so that we can reuse what we wrote. So I tried to make a Stack by inheriting Pair. class Stack(Pair): pass >>> Stack(1, Empty()) Stack(1, Empty()) Then I wrote pop and push. >>> Stack(1, Empty()).pop() 1 >>> Stack(1, Empty()).push(2) Stack(2, Stack(1, Empty())) So far so good. Now let me show you what I can't do. (*) The difficulty of encapsulating a union The Lisp-like sequences we're building here are union-like data structures. A /sequence/ is either Empty() or Pair(..., /sequence/). I have not found a way to represent this either-or datastructure with a class. For example, there is no way right now to build an empty Stack by invoking the Stack constructor. >>> Stack() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Pair.__init__() missing 2 required positional arguments: 'first' and 'rest' As I designed, an empty Stack is represented by Empty(), which is a whole other object. Users will have to know this. I wish I did not have to burden my users with such knowledge. For instance, I wish the answer was "Stack()" to the question of -- ``how can I build an empty stack?'' My desire seems to imply that I need a union-like data structure. If Stack is invoked with no arguments, it should produce Empty(), otherwise it produces Pair() as it does today. How can I achieve that? (*) Code class Pair: def __init__(self, first, rest): if not isinstance(rest, Pair) and not isinstance(rest, Empty): raise ValueError("rest must be Empty or Pair") self.first = first self.rest = rest def fromIterable(it): if len(it) == 0: return Empty() else: return Pair(it[0], Pair.fromIterable(it[1:])) def __str__(self): return "{}({!r}, {})".format(self.__class__.__name__, self.first, str(self.rest)) def __repr__(self): return str(self) def __len__(self): return 1 + self.rest.__len__() class Empty: def __len__(self): return 0 def __str__(self): return "Empty()" def __repr__(self): return self.__str__() def __new__(clss): if not hasattr(clss, "saved"): clss.saved = super().__new__(clss) return clss.saved class Stack(Pair): def pop(self): return self.first def push(self, x): return Stack(x, self) From jshem at yaxenu.org Sun Oct 30 10:54:24 2022 From: jshem at yaxenu.org (Julieta Shem) Date: Sun, 30 Oct 2022 11:54:24 -0300 Subject: an oop question References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> Message-ID: <86k04hmkf3.fsf@yaxenu.org> ram at zedat.fu-berlin.de (Stefan Ram) writes: > Julieta Shem <jshem at yaxenu.org> writes: >>My desire seems to imply that I need a union-like data structure. > > You only need to worry about such things in languages with > static typing. For example, to have a function that can > sometimes return an int value and at other times a string > value in C, one would need a union. > > In Python with its dynamic typing, one does not need unions. > > def an_int_sometimes_and_sometimes_a_string( x ): > if x: > return 2 > else: > return "two" Nice. This means that I can solve my stack-union problem by writing a procedure --- say stack(...) --- that sometimes gives me Empty() and sometimes gives me Stack(). >>> stack() Empty() >>> stack(1,2,3,4) Stack(4, Stack(3, Stack(2, Stack(1, Empty())))) The user interface of this non-empty case is that we're stacking up the arguments, hence the number 1 ends up at the bottom of the stack. def stack(*args): if len(args) == 0: return Empty() else: return Stack(args[-1], stack(*args[:-1])) I realize now that I'm using the same solution of the /open()/ procedure. Depending on the arguments, open() produces a different type of object. > . If you should, however, be talking about the new "type hints": > These are static and have "Union", for example, "Union[int, str]" > or "int | str". I ended up locating such features of the language in the documentation, but I actually am not interested in declaring the type to the compiler (or to the reader). I was looking for a solution like yours --- thank you! ---, although I was hoping for handling that situation in the construction of the Stack object, which was probably why I did not find a way out. Right now I'm looking into __new__() to see if it can somehow produce one type or another type of object depending on how the user has invoked the class object. Terminology. By ``invoking the class object'' I mean expressions such as Class1() or Class2(). ``Class1'' represents the object that represents the class 1. Since the syntax is that of procedure invokation, I say ``invoking the class object''. From yassine.naasri at gmail.com Sun Oct 30 10:57:14 2022 From: yassine.naasri at gmail.com (Yassine Nasri) Date: Sun, 30 Oct 2022 15:57:14 +0100 Subject: Weired behaviour - The slice of empty string not return an error Message-ID: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> Hello, len('') # => 0''[0] # => error''[::] # => ''''[::] # <=> ''[0:len(''):1] the syntax of slice: slice(start, end, step) The start in ''[::] equivalent at index 0 of the '' Since the index 0 of '' returns an error. The ''[::] should not return an error logically. Best regards From yassine.naasri at gmail.com Sun Oct 30 10:59:41 2022 From: yassine.naasri at gmail.com (Yassine Nasri) Date: Sun, 30 Oct 2022 15:59:41 +0100 Subject: Weired behaviour - The slice of empty string not return an error In-Reply-To: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> References: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> Message-ID: <CAMXb-5ngFYTgo=Y8CW3HbAt+xBTkJAi=4KN3-c0-jMAEUrn4Xg@mail.gmail.com> PS: The ''[::] should return an error logically. Le dim. 30 oct. 2022 ? 15:57, Yassine Nasri <yassine.naasri at gmail.com> a ?crit : > Hello, > > len('') # => 0''[0] # => error''[::] # => ''''[::] # <=> ''[0:len(''):1] > > the syntax of slice: > > slice(start, end, step) > > The start in ''[::] equivalent at index 0 of the '' > > Since the index 0 of '' returns an error. > > The ''[::] should not return an error logically. > > > Best regards > From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 30 12:52:02 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 30 Oct 2022 16:52:02 +0000 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> Message-ID: <tjma3i$gqh$1@gioia.aioe.org> ?s 10:26 de 30/10/22, Peter J. Holzer escreveu: > On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: >> ?s 22:34 de 29/10/22, dn escreveu: >>> Solution (below) will not work if the mention of Foos in GLOBALS is a >>> forward-reference. >>> Either move GLOBALS to suit, or surround "Foos" with quotes. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >> This is the problem for me. > > Quotes are a bit ugly, but why are they a problem? > > [...] > >> The funny thing is that if I replace foos by Foos it works because it gets >> known by the initial initialization :-) ! >> >> ________________________ >> from typing import List, Optional >> >> class GLOBALS: >> Foos: Optional[Foos]=None > [...] >> class Foos: > > That seems like a bug to me. What is the ?Foos? in ?Optional[Foos]? > referring to? > > If it's the class attribute ?Foos? then that's not a type and even if > its type is inferred that's not the same as ?Optional[it's type]?, or is > it? > > If it's referring to the global symbol ?Foos? (i.e. the class defined > later) that hasn't been defined yet, so it shouldn't work (or > alternatively, if forward references are allowed it should always work). The problem is exactly this. Is there anything to do without loosing my script structure and usual practice? The forward reference only is needed to the "typing thing". Even if I declare class "Foos: pass" before, then another error arises - something like "already declared" below. From jshem at yaxenu.org Sun Oct 30 13:30:08 2022 From: jshem at yaxenu.org (Julieta Shem) Date: Sun, 30 Oct 2022 14:30:08 -0300 Subject: an oop question References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> Message-ID: <86leoxi5i7.fsf@yaxenu.org> Julieta Shem <jshem at yaxenu.org> writes: [...] >> . If you should, however, be talking about the new "type hints": >> These are static and have "Union", for example, "Union[int, str]" >> or "int | str". > > I ended up locating such features of the language in the documentation, > but I actually am not interested in declaring the type to the compiler > (or to the reader). > > I was looking for a solution like yours --- thank you! ---, although I > was hoping for handling that situation in the construction of the Stack > object, which was probably why I did not find a way out. Right now I'm > looking into __new__() to see if it can somehow produce one type or > another type of object depending on how the user has invoked the class > object. > > Terminology. By ``invoking the class object'' I mean expressions such > as Class1() or Class2(). ``Class1'' represents the object that > represents the class 1. Since the syntax is that of procedure > invokation, I say ``invoking the class object''. An experiment. What's my definition of Stack? It's either Empty or Pair, so it's a union. So let us create two inner classes (that is, inner to Stack) and make them behave just like Empty and Pair. Using __new__(), we can produce a Stack object that is sometimes Empty() and sometimes Pair(...). class Stack: class StackEmpty(Empty): pass class StackPair(Pair): pass def __new__(clss, *args): if len(args) == 0: return Stack.StackEmpty() else: return Stack.StackPair(*args) This does it. However, we are exposing the different types to the user. >>> Stack() Empty() >>> Stack(1, Stack()) Pair(1, Empty()) Since we have our own copies of Empty and Pair inside Stack, we change their representation. class Stack: class StackEmpty(Empty): def __str__(self): return "Stack()" def __repr__(self): return str(self) class StackPair(Pair): def __str__(self): return "Stack({!r}, {})".format(self.first, str(self.rest)) def __repr__(self): return str(self) [...] >>> Stack() Stack() >>> Stack(1, Stack()) Stack(1, Stack()) That's it. That's what I was looking for. However, I don't really like the OOP approach here because of what's going to happen next. Now we are free to move on with implementing push and pop, say. But since Stack is really a union, we need to define push and pop on each of these inner types that make up Stack. Let's do it and see what we get. class StackEmpty(Empty): [...] def pop(self): raise ValueError("cannot pop from an empty stack") def push(self, x): return Stack(x, self) class StackPair(Pair): def pop(self): return self.first def push(self, x): return Stack(x, self) The job is done. >>> Stack().push("it") Stack('it', Stack()) >>> Stack(1, Stack()).push(2).push(3) Stack(3, Stack(2, Stack(1, Stack()))) We may observe that we had to write the same exact procedure /push/ in both types. Sounds funny to say that it seems that we are too modular here. I'm pretty sure you'll find a way to grab the procedure of one class and apply it on the other, so I really think there's a way out of not wasting keyboard-typing work and keeping things with a ``single point of control''. (*) Complete code class Stack: class StackEmpty(Empty): def __str__(self): return "Stack()" def __repr__(self): return str(self) def pop(self): raise ValueError("cannot pop from an empty stack") def push(self, x): return Stack(x, self) class StackPair(Pair): def __str__(self): return "Stack({!r}, {})".format(self.first, str(self.rest)) def __repr__(self): return str(self) def pop(self): return self.first def push(self, x): return Stack(x, self) def __new__(clss, *args): if len(args) == 0: return Stack.StackEmpty() else: return Stack.StackPair(*args) From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 30 15:00:30 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 30 Oct 2022 19:00:30 +0000 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> <tjma3i$gqh$1@gioia.aioe.org> <lose-20221030180606@ram.dialup.fu-berlin.de> Message-ID: <tjmhke$1o6a$1@gioia.aioe.org> ?s 17:06 de 30/10/22, Stefan Ram escreveu: > Paulo da Silva <p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> writes: >> Is there anything to do without loosing my script structure and usual >> practice? > > to lose (losing): to stop having something > to loose (loosing): to let or make loose (see next line) > loose (adj.): not firmly attached/tied/fastened/controlled > to loosen: similar to "to loose" It was a keyboard bounce ;-) How about answering the question? Thank you. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Sun Oct 30 15:13:56 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Sun, 30 Oct 2022 19:13:56 +0000 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> Message-ID: <tjmidk$2mn$1@gioia.aioe.org> ?s 22:34 de 29/10/22, dn escreveu: > Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the > original: > > ??? GLOBALS.foos: Optional[Foos]=Foos() > > but not the fall-back: > > ??? GLOBALS.foos=Foos() > > > Must admit, the first query coming to mind was: why is the typing taking > place at initialisation-time, rather than within the (class) definition? > At definition time "foos" has already been typed as None by implication! > > > Solution (below) will not work if the mention of Foos in GLOBALS is a > forward-reference. Either move GLOBALS to suit, or surround "Foos" with > quotes. Somehow I missed this sentence the 1st. time I read this post :-( This is good enough to me! Thank you. I didn't know about this "quoting" thing. Regards Paulo From pastgio at units.it Sun Oct 30 16:06:00 2022 From: pastgio at units.it (Giorgio Pastore) Date: Sun, 30 Oct 2022 21:06:00 +0100 Subject: an oop question In-Reply-To: <86k04hmkf3.fsf@yaxenu.org> References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> Message-ID: <js83p8FmhjtU1@mid.individual.net> Il 30/10/22 15:54, Julieta Shem ha scritto: > ram at zedat.fu-berlin.de (Stefan Ram) writes: > >> Julieta Shem <jshem at yaxenu.org> writes: >>> My desire seems to imply that I need a union-like data structure. >> >> You only need to worry about such things in languages with >> static typing. For example, to have a function that can >> sometimes return an int value and at other times a string >> value in C, one would need a union. >> >> In Python with its dynamic typing, one does not need unions. >> >> def an_int_sometimes_and_sometimes_a_string( x ): >> if x: >> return 2 >> else: >> return "two" > > Nice. This means that I can solve my stack-union problem by writing a > procedure --- say stack(...) --- that sometimes gives me Empty() and > sometimes gives me Stack(). > I think that Stefan Ram's suggestion provides a solution to the problem of the stack, but not in a real OOP flavor. You may find useful to learn about the possibilities of using Python tools to implement a stack data structure and its manipulation methods. A good introduction is at https://realpython.com/how-to-implement-python-stack/ Giorgio From PythonList at DancesWithMice.info Sun Oct 30 18:30:40 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 31 Oct 2022 11:30:40 +1300 Subject: Fwd: A typing question In-Reply-To: <tjkvmc$14t5$1@gioia.aioe.org> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <ff63879c-2079-cfe0-4a61-1b9372f25dac@DancesWithMice.info> <mailman.831.1667097177.20444.python-list@python.org> <tjkvmc$14t5$1@gioia.aioe.org> Message-ID: <c8ac81f6-3723-916c-44bc-a226c6349b16@DancesWithMice.info> On 30/10/2022 17.48, Paulo da Silva wrote: > ?s 02:32 de 30/10/22, dn escreveu: >> On 30/10/2022 11.59, Paulo da Silva wrote: >>>> Solution (below) will not work if the mention of Foos in GLOBALS is >>>> a forward-reference. Either move GLOBALS to suit, or surround "Foos" >>>> with quotes. >>> This is the problem for me. So far, without typing, I used to have >>> some config and globals classes, mostly to just group definitions an >>> make the program more readable. A matter of taste and style. >> >> Agreed, a good practice. > Thank you. >> >> >>> Now, "typing" is breaking this, mostly because of this forward >>> reference issue. >> >> As a first step, use the quotation-marks to indicate that such will be >> defined later in the code:- >> >>> class GLOBALS: >>> ??? Foos: Optional[Foos]=None >> >> class GLOBALS: >> ???? Foos: Optional["Foos"]=None >> >> >> Later, as gather (typing) expertise, can become more sophisticated, >> as-and-when... >> >> >>> The funny thing is that if I replace foos by Foos it works because it >>> gets known by the initial initialization :-) ! >> >> Is the objective to write (good) code, or merely to satisfy the >> type-checker? >> >> Something that is misleading is not going to be appreciated by others >> (including the +6-months you), eg >> >> a = a + 1?? # decrement total >> >> Typing is not compulsory, and has been designed so that we can >> implement it a bit at a time, eg only one function amongst many >> contained by a module - if that's the only code that requires >> maintenance/update. >> >> Best not to create "technical debt" though! >> > The main idea is to eventually catch some, otherwise "hidden", errors > and produce better and cleaner code. Documentation is also a must. Good idea! All-along typing has been regarded as a tool for dev.aids, eg IDEs like PyCharm and tools such as mypy - rather than a (compulsory) component of the Python language itself. This means the folk who decide they don't like the idea can happily (and safely) ignore it - and continue to write code in perfect-Python. Also, that 'old program[me]s' will continue to operate, just as well as they ever did, without any reference to the typing library/ies at all. So, there is no imposed-cost, or 'pressure' to (wait to) upgrade (such as there was with the jump from Python 2 to Python 3). IMHO I'm finding that the auto-checking performed by the IDE is very helpful and stops my imagination from outstripping my coding-abilities (in the way that my eyes for chocolate cake are bigger than my stomach!). I'll go so far as to say that the discipline imposed/flagged by typing has been more beneficial, than my flirtation with an 'AI assistant' suggesting what I should code next! The assistant rarely seems to correctly anticipate my thinking*, whereas typing pulls me up when the code falls-short and prevents me from falling flat on my face! * which may say something unfortunate about my coding/design, or may simply show that SODD (Stack Overflow Driven Development - or the GitHub equivalent) leaves much to be desired. Hence the gold-plated advice: never copy-paste code without understanding it first! As time goes by, 'The Python Gods' have been introducing more and more capability under the typing banner. Which makes the policy as-outlined, the sensible (and parallel) course. S/w architecture and coding-quality books talk about "The Boy Scout Rule" (leave the camp-site in better condition than you found it). Accordingly, when performing user-specified updates, while we are 'there', we have the option/ability to add typing to a module/class/function - just as we might perform other "refactoring" tasks (one 'green-thumb' I know, referred to it as 'gardening'). Evidently, the OP introduced typing into his/her code-base with the likes of List*. Thereafter, added the Optional, er, option. Now, we're talking about forward-references. Plus alluding to more recent developments (many of which are version-dependent!). Accordingly, we see another attribute of a gradual-introduction policy - the practitioner learning and becoming confident that (s)he has mastered basic techniques, before striding onwards to 'the next level'! * and for the above reason, I wondered, belatedly, if earlier advice to 'graduate' to "list", might be premature. PS and on a personal note, this policy is the one I'm following. So, given that we-two are on the same track, we must be "correct" - and also the best Python programmers in the world! (pardon me, I seem over-taken by a coughing fit...) YMMV! -- Regards =dn From rosuav at gmail.com Sun Oct 30 18:31:01 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 31 Oct 2022 09:31:01 +1100 Subject: an oop question In-Reply-To: <86leoxi5i7.fsf@yaxenu.org> References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> <86leoxi5i7.fsf@yaxenu.org> Message-ID: <CAPTjJmqibdNc+ehd7=Hc1w5ypHCpJpYjZd1_oMinHE6pu6Ax0Q@mail.gmail.com> On Mon, 31 Oct 2022 at 09:05, Julieta Shem <jshem at yaxenu.org> wrote: > > Julieta Shem <jshem at yaxenu.org> writes: > > [...] > > >> . If you should, however, be talking about the new "type hints": > >> These are static and have "Union", for example, "Union[int, str]" > >> or "int | str". > > > > I ended up locating such features of the language in the documentation, > > but I actually am not interested in declaring the type to the compiler > > (or to the reader). > > > > I was looking for a solution like yours --- thank you! ---, although I > > was hoping for handling that situation in the construction of the Stack > > object, which was probably why I did not find a way out. Right now I'm > > looking into __new__() to see if it can somehow produce one type or > > another type of object depending on how the user has invoked the class > > object. > > > > Terminology. By ``invoking the class object'' I mean expressions such > > as Class1() or Class2(). ``Class1'' represents the object that > > represents the class 1. Since the syntax is that of procedure > > invokation, I say ``invoking the class object''. > > An experiment. What's my definition of Stack? It's either Empty or > Pair, so it's a union. So let us create two inner classes (that is, > inner to Stack) and make them behave just like Empty and Pair. Using > __new__(), we can produce a Stack object that is sometimes Empty() and > sometimes Pair(...). > The most straight-forward way to represent this concept in an object-oriented way is subclassing. class Stack: ... # put whatever code is common here class Empty(Stack): ... # put Empty-specific code here, possibly overriding Stack methods class Pair(Stack): ... # ditto, overriding or augmenting as needed This way, everything is an instance of Stack, but they are still distinct types for when you need to distinguish. ChrisA From PythonList at DancesWithMice.info Sun Oct 30 18:34:58 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 31 Oct 2022 11:34:58 +1300 Subject: Fwd: A typing question In-Reply-To: <lose-20221030180606@ram.dialup.fu-berlin.de> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> <tjma3i$gqh$1@gioia.aioe.org> <lose-20221030180606@ram.dialup.fu-berlin.de> Message-ID: <41e045af-c35a-6012-9a1a-aa2e6e4c4bfc@DancesWithMice.info> On 31/10/2022 06.06, Stefan Ram wrote: > Paulo da Silva <p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> writes: >> Is there anything to do without loosing my script structure and usual >> practice? > > to lose (losing): to stop having something > to loose (loosing): to let or make loose (see next line) > loose (adj.): not firmly attached/tied/fastened/controlled > to loosen: similar to "to loose" Hay, your write*! Well done. There's many a native-speaker who doesn't know the distinction, or doesn't care about accuracy. It's a pity that there's no decent typing module for the English language! * yes, each word sounds about-right, but is totally wrong... -- Regards, =dn From rosuav at gmail.com Sun Oct 30 18:44:30 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 31 Oct 2022 09:44:30 +1100 Subject: Fwd: A typing question In-Reply-To: <41e045af-c35a-6012-9a1a-aa2e6e4c4bfc@DancesWithMice.info> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> <tjma3i$gqh$1@gioia.aioe.org> <lose-20221030180606@ram.dialup.fu-berlin.de> <41e045af-c35a-6012-9a1a-aa2e6e4c4bfc@DancesWithMice.info> Message-ID: <CAPTjJmqAWvZdXzYAzm-OcxsDL0ta-4fCY5GHzG+pdErx6qOEkg@mail.gmail.com> On Mon, 31 Oct 2022 at 09:39, dn <PythonList at danceswithmice.info> wrote: > > On 31/10/2022 06.06, Stefan Ram wrote: > > Paulo da Silva <p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> writes: > >> Is there anything to do without loosing my script structure and usual > >> practice? > > > > to lose (losing): to stop having something > > to loose (loosing): to let or make loose (see next line) > > loose (adj.): not firmly attached/tied/fastened/controlled > > to loosen: similar to "to loose" > > > Hay, your write*! > > Well done. There's many a native-speaker who doesn't know the > distinction, or doesn't care about accuracy. > I'm curious to what extent sloppy English correlates with sloppy code. Do people care about learning proper Python but not about proper English, or do they think there's no such thing as proper English just because there's no English Steering Council? A lot of people seem to treat English the way web browsers treat HTML - as long as you can make some sense out of it, it's good enough. Some nerds treat English the way the W3C treats HTML - there actually is a standard and everything has defined rules. I know which camp I prefer to communicate with. ChrisA From gweatherby at uchc.edu Sun Oct 30 20:03:27 2022 From: gweatherby at uchc.edu (Weatherby,Gerard) Date: Mon, 31 Oct 2022 00:03:27 +0000 Subject: an oop question In-Reply-To: <86y1sxmmvo.fsf@yaxenu.org> References: <86y1sxmmvo.fsf@yaxenu.org> Message-ID: <SA1PR14MB585584E0C9313370167F2C2BB9379@SA1PR14MB5855.namprd14.prod.outlook.com> I don?t understand your implementation enough to comment specifically. What?s the definition of Pair? (i.e. what methods and public attributes does it have?) (I manage to escape Lisp as an undergrad) To answer your question generally, Union?s are not OO. If you want Pair and Stack to have the same interface create an abstract base class and derive both of them from it. https://docs.python.org/3/library/abc.html From: Python-list <python-list-bounces+gweatherby=uchc.edu at python.org> on behalf of Julieta Shem <jshem at yaxenu.org> Date: Sunday, October 30, 2022 at 5:51 PM To: python-list at python.org <python-list at python.org> Subject: an oop question *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. *** I have a question about a particular case I'm working on. I'm studying OOP. To ask the question, I'm going to have to introduce you my context here, so you'll need to bear with me. If you'd like to see the question right away, go to the section ``My difficulty in encapsulating a union''. (*) Introduction I wrote the classes class Empty: ... class Pair: ... With them, I can (sort of) make a union of them and build a Lisp-like list by defining that my Lisp-like list is either Empty or a Pair. For instance, here's a Lisp-like sequence that represents the string "abc". >>> Pair.fromIterable("abc") Pair('a', Pair('b', Pair('c', Empty()))) So far so good. (``Full'' code at the end of this message, if you'd like to more carefully look into my reasoning there.) (*) How to build a stack? These Lisp-like sequences are clearly a stack. You pop an element from it by grabbing the first element. You push an element on to it by just pairing the new element with the current stack. For instance, let's pop the 1-string "a" off of the stack. >>> ls = Pair.fromIterable("abc") >>> ls.first 'a' >>> ls = ls.rest >>> ls Pair('b', Pair('c', Empty())) Done. Let's push it back on. >>> ls = Pair("a", ls) >>> ls Pair('a', Pair('b', Pair('c', Empty()))) So far so good, but when it comes to building a better user interface for it I have no idea how to do it. I think one of the purposes of OOP is to organize code hierarchically so that we can reuse what we wrote. So I tried to make a Stack by inheriting Pair. class Stack(Pair): pass >>> Stack(1, Empty()) Stack(1, Empty()) Then I wrote pop and push. >>> Stack(1, Empty()).pop() 1 >>> Stack(1, Empty()).push(2) Stack(2, Stack(1, Empty())) So far so good. Now let me show you what I can't do. (*) The difficulty of encapsulating a union The Lisp-like sequences we're building here are union-like data structures. A /sequence/ is either Empty() or Pair(..., /sequence/). I have not found a way to represent this either-or datastructure with a class. For example, there is no way right now to build an empty Stack by invoking the Stack constructor. >>> Stack() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Pair.__init__() missing 2 required positional arguments: 'first' and 'rest' As I designed, an empty Stack is represented by Empty(), which is a whole other object. Users will have to know this. I wish I did not have to burden my users with such knowledge. For instance, I wish the answer was "Stack()" to the question of -- ``how can I build an empty stack?'' My desire seems to imply that I need a union-like data structure. If Stack is invoked with no arguments, it should produce Empty(), otherwise it produces Pair() as it does today. How can I achieve that? (*) Code class Pair: def __init__(self, first, rest): if not isinstance(rest, Pair) and not isinstance(rest, Empty): raise ValueError("rest must be Empty or Pair") self.first = first self.rest = rest def fromIterable(it): if len(it) == 0: return Empty() else: return Pair(it[0], Pair.fromIterable(it[1:])) def __str__(self): return "{}({!r}, {})".format(self.__class__.__name__, self.first, str(self.rest)) def __repr__(self): return str(self) def __len__(self): return 1 + self.rest.__len__() class Empty: def __len__(self): return 0 def __str__(self): return "Empty()" def __repr__(self): return self.__str__() def __new__(clss): if not hasattr(clss, "saved"): clss.saved = super().__new__(clss) return clss.saved class Stack(Pair): def pop(self): return self.first def push(self, x): return Stack(x, self) -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!iK-T12707FwUmb1Qqxlxawj0i9z1tR9aCPWPoHzh5veCzlaFBY9pKfFZwGqg3sDjUqLPC2IZgGw4QI3sRg$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!iK-T12707FwUmb1Qqxlxawj0i9z1tR9aCPWPoHzh5veCzlaFBY9pKfFZwGqg3sDjUqLPC2IZgGw4QI3sRg$> From PythonList at DancesWithMice.info Sun Oct 30 20:50:03 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 31 Oct 2022 13:50:03 +1300 Subject: Fwd: A typing question In-Reply-To: <CAPTjJmqAWvZdXzYAzm-OcxsDL0ta-4fCY5GHzG+pdErx6qOEkg@mail.gmail.com> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> <tjma3i$gqh$1@gioia.aioe.org> <lose-20221030180606@ram.dialup.fu-berlin.de> <41e045af-c35a-6012-9a1a-aa2e6e4c4bfc@DancesWithMice.info> <CAPTjJmqAWvZdXzYAzm-OcxsDL0ta-4fCY5GHzG+pdErx6qOEkg@mail.gmail.com> Message-ID: <c2dabfc0-a931-bde6-59a1-ba337a442ca7@DancesWithMice.info> On 31/10/2022 11.44, Chris Angelico wrote: > On Mon, 31 Oct 2022 at 09:39, dn <PythonList at danceswithmice.info> wrote: >> >> On 31/10/2022 06.06, Stefan Ram wrote: >>> Paulo da Silva <p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt> writes: >>>> Is there anything to do without loosing my script structure and usual >>>> practice? >>> >>> to lose (losing): to stop having something >>> to loose (loosing): to let or make loose (see next line) >>> loose (adj.): not firmly attached/tied/fastened/controlled >>> to loosen: similar to "to loose" >> >> >> Hay, your write*! >> >> Well done. There's many a native-speaker who doesn't know the >> distinction, or doesn't care about accuracy. >> > > I'm curious to what extent sloppy English correlates with sloppy code. > Do people care about learning proper Python but not about proper > English, or do they think there's no such thing as proper English just > because there's no English Steering Council? > > A lot of people seem to treat English the way web browsers treat HTML > - as long as you can make some sense out of it, it's good enough. Some > nerds treat English the way the W3C treats HTML - there actually is a > standard and everything has defined rules. I know which camp I prefer > to communicate with. There are two distinctions to make: what is "correct", and how correctly we practice! Various languages do have a 'standards body', eg French and the group known as "l'Acad?mie (fran?aise)". However, no matter how much they try to push-back against the encroachment of words from other languages (eg "le weekend"), even they admit that it is a losing battle (see also: King Canute). English is, and has long-been, an "acquisitive language". It takes words from other languages, often as attempted-homophones, and makes them "English": verandah, foreign, algebra, ... (and seeing I mentioned French: "maitre d'" because it makes the restaurant sound 'posh'; champagne because you can then charge more for the bubbles, and omelet/omelette because I'm feeling hungry...). Indeed yous-Australians are also manipulators of the language, eg "tradies" for tradesmen/trades-people (see also: "They're a Weird Mob" - in case you haven't read that hilarious piece of Aussie Kulcha). There have been various attempts at standardising English. Indeed for our Internet-based training courses and courseware, I went looking for an 'international English'. There is no such thing. The closest is more to do with accent than text, ie speaking the Queen's/King's English, is really a euphemism for a (plummy) Oxford accent (or BBC accent - also fading into the past). A good starting-point: https://www.cambridge.org/highereducation/books/the-cambridge-encyclopedia-of-the-english-language/2B10AC8766B73D09955C899572C1E7EC#overview - a tome compiled by a man living in Wales (go figure!). The earliest attempts would include Samuel Johnson's Dictionary of the English Language (which preceded 'your' Lewis Carroll's playing with language by about half a century). Around-about one-century after that came the OED (Oxford English Dictionary), which is the closest thing to an idea of 'standard spelling'. (and at times differs significantly from alternate tomes describing American-English). As for grammar, I must admit deferring (and devolving?) such to style manuals, such as The Times of London, Strunk and White, etc. (but perhaps only later and lesser: Kernighan and Plauger's similarly named "Elements of Programming Style"). In this case, my multi-cultural education (or lack of application to my school-work?) has caused me many a stumble. Certainly, I've never taught the subject. Perhaps someone is better-acquainted with works used by The British Council, et al, in their English as a Second Language (and related) courses? The other side of this topic, that of accuracy and precision, involves aspects which were driven into us at school - that is, those of us with Optional[grey] hair! These days, teaching good-grammar, spelling, and so-on, are deemed unnecessarily restrictive, perhaps even cruel, but certainly far too boring (see also: "joined-up" hand-writing). "Drill" (aka "deliberate practice") is rarely employed as a teaching/learning technique in schools. Cue "amo, amas, amat, amamus, amatis, amant" (Latin - although quite why, as six-year olds, the teachers ("Masters") thought we should be speaking of love escapes me) and "Je suis, tu es, il est, ..." (French - which always reminds me of Rodin's sculpture and Descartes exclamation)* I've even (as an adult) had a (school) Department Head reply to such criticism with "but you understood me, didn't you?". So, with teachers like that, the kids are 'on a hiding to nothing'. The prevailing-theory seems to be that 'you'll pick it up as you go-along'. However, empirical evidence suggests otherwise. I've even met voracious readers who admit that their spelling is at the lousy-end of any metric, busting that myth well-and-truly! Traditionally 'computer people' have been assumed to need a good grounding in math[s]. Although, I haven't met anyone recently whose computing degree includes delving into Numerical Analysis - which explains the two recent threads (here and/or Tutor) asking why floating-point numbers are not always accurate/precise. Indeed, it's not hard to find ComSc graduates who don't know that 1 + 1 = 10 (binary) nor octal, nor hex[adecimal]... (cue: (timely) joke about not knowing the difference between Halloween and Christmas) There are observations (regret: have failed to lift-out a paper or a web.ref, but will keep an eye out...) that a better preparation for programming might well be human-language courses. Even the experience of grappling with a non-native language, both the learning and the execution, are readily transferable to computing. Plus, appreciating the subtleties of language (see elsewhere, list ~= stack) prepares one for the task of communicating both to human and machine, concurrently! If not [in the] right, the teacher, mentioned earlier, was correct: I did understand him. However, even basic communication theory illustrates that his lack of effort in 'transmitting' required extra effort from the 'receiver'. A computer/compiler will not invest (much) "extra" - despite the herculean efforts to improve Traceback explanations in recent Python releases. Many thanks to those involved!). In source-code, precision is 'rewarded'; but lack of precision is quickly and decisively 'punished'. Doesn't the compiler enforce a discipline upon us? Does that mean that accepting such discipline is a (necessary) early step towards the profession? Indeed, perhaps the constant mental struggle against an implacable machine; which regularly, and almost gleefully, tells us 'you are wrong'; is a reason why so many leave the profession - frustrated, angry, disappointed, mentally-exhausted, ego-dented, ... (sadly, not the only (sensible) reason for leaving!) Also, programming is something of a team-sport. We regularly come-across correspondents to this list asking questions without suitable and sufficient background information. Being able to ask a question and describe a problem is a skill - as much as describing the solution in Python. Indeed the famous push-back for such deficit is "Rubber Duck Problem Solving", and the phenomenon that the process of organising one's thoughts in order to best express them to another, is likely to throw-up a/the solution. When that doesn't work, the quality of the question and its communication will directly affect the (speed and) quality of an answer - as well as the 'cost' of the distraction to the 'helper'. Our common understanding of the problem domain, is key to communication. (and a generator of jargon, or extensions to the language!) When it comes to CVs/resum?s (see what I did there?), I must admit that the most egregious of errors in spelling or grammar do ensure that an applicant's 'work' is quickly routed to "file 13" (an American-English term, many other English-speakers will not have heard previously). IMHO, I prefer someone who'll *do* the work, over someone who'll make me work. YMMV! Surely someone who mis-types and/or misspells, and has to 'take a second run at it' after Python objects, will take longer to complete the same task as someone who is accurate and 'gets it right first-time'? (indeed, would better construction of that sentence read: "Surely someone who mis-types and/or misspells, and suffering objections from Python, has to 'take a second run at it', will take longer...") Alternately, I'm just an old f...? * that said, the languages I've learned since-school have all been through "immersion" in another culture; which I'd suggest is a more effective method (yet has its own dimension of "cruel"!) - but perhaps so, only because I had the 'base' (or the tools?) inculcated through my schooling (such as it was). Contrarily, my (somewhat younger) brother-in-law never studied languages at school, and struggled (and suffered) when he went to work in Germany - and was disgusted (envious) when I arrived and appeared to absorb the language 'by osmosis' (and a preparedness to make a fool of myself - something also learned at school, and impressed upon me by the Masters, without any trace of irony, but sometimes using impress-ively 'heavy weapons'...) -- Regards, =dn From PythonList at DancesWithMice.info Sun Oct 30 20:58:28 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 31 Oct 2022 13:58:28 +1300 Subject: an oop question In-Reply-To: <stack-20221030212024@ram.dialup.fu-berlin.de> References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> <js83p8FmhjtU1@mid.individual.net> <stack-20221030212024@ram.dialup.fu-berlin.de> Message-ID: <2bf88e5b-d0ea-e285-e22c-a7c78938c6e3@DancesWithMice.info> On 31/10/2022 09.22, Stefan Ram wrote: > Giorgio Pastore <pastgio at units.it> writes: >> You may find useful to learn about the possibilities of using Python >> tools to implement a stack data structure and its manipulation methods. >> A good introduction is at >> https://realpython.com/how-to-implement-python-stack/ > > I can't see how lists are not stacks. Agreed - in terms of functionality(!) > |>>> s=[] > |>>> s.append(1) > |>>> s.append(2) > |>>> s.pop() > |2 > |>>> s.pop() > |1 > |>>> s.pop() > |Traceback (most recent call last): > | File "<stdin>", line 1, in <module> > |IndexError: pop from empty list > > So, for practical purposes, there is no need to implement a > stack class as far as I can understand it. > > Maybe the OP wanted to implement a stack in a special way, > so that this stack is immutable and its implementation is > based on something like dotted pairs. Code is for humans to read too. Accordingly, instead of "s", preference for "stack" - per OP terminology. The OP has coded pop() and push() methods, which are familiar/taught as 'the' stack operations in every 'intro to algorithms' (or intermediate 'data-structures') class. Sadly, whereas there is list.pop(), the equivalent "push" method is append(). Thus, a (small) dissonance in one's mind. Writing a Stack class is unnecessary - at least given list, it is. However, having called the structure "stack" to be descriptive and helpful, it seems logical to continue by referring to the methods as "push" and "pop". (which is why many of us have such 'utilities'/snippets sitting-ready in a personal library) The OP has already coded such, so no cost to keep. (returning to the OP) Like @Gerard, am confused. There are two types: Pair and Empty. Thereafter the need is to keep them on a stack. The stack is a collection, an aggregate of 'whatever'. Why inherit from/to Stack? (is this a 'Lisp thing'?) -- Regards, =dn From python at mrabarnett.plus.com Sun Oct 30 23:05:22 2022 From: python at mrabarnett.plus.com (MRAB) Date: Mon, 31 Oct 2022 03:05:22 +0000 Subject: Weired behaviour - The slice of empty string not return an error In-Reply-To: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> References: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> Message-ID: <24ded018-e2c7-9cfc-dddf-2c3d6649e833@mrabarnett.plus.com> On 2022-10-30 14:57, Yassine Nasri wrote: > Hello, > > len('') # => 0''[0] # => error''[::] # => ''''[::] # <=> ''[0:len(''):1] > > the syntax of slice: > > slice(start, end, step) > > The start in ''[::] equivalent at index 0 of the '' > > Since the index 0 of '' returns an error. > > The ''[::] should not return an error logically. > Python uses half-open ranges. It excludes the end. ''[0:0:1] starts at index 0 but ends at and excludes index 0. From jshem at yaxenu.org Sun Oct 30 20:38:51 2022 From: jshem at yaxenu.org (Julieta Shem) Date: Sun, 30 Oct 2022 21:38:51 -0300 Subject: an oop question References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> <86leoxi5i7.fsf@yaxenu.org> <CAPTjJmqibdNc+ehd7=Hc1w5ypHCpJpYjZd1_oMinHE6pu6Ax0Q@mail.gmail.com> <mailman.840.1667169075.20444.python-list@python.org> Message-ID: <86v8o0hlno.fsf@yaxenu.org> Chris Angelico <rosuav at gmail.com> writes: > On Mon, 31 Oct 2022 at 09:05, Julieta Shem <jshem at yaxenu.org> wrote: >> >> Julieta Shem <jshem at yaxenu.org> writes: >> >> [...] >> >> >> . If you should, however, be talking about the new "type hints": >> >> These are static and have "Union", for example, "Union[int, str]" >> >> or "int | str". >> > >> > I ended up locating such features of the language in the documentation, >> > but I actually am not interested in declaring the type to the compiler >> > (or to the reader). >> > >> > I was looking for a solution like yours --- thank you! ---, although I >> > was hoping for handling that situation in the construction of the Stack >> > object, which was probably why I did not find a way out. Right now I'm >> > looking into __new__() to see if it can somehow produce one type or >> > another type of object depending on how the user has invoked the class >> > object. >> > >> > Terminology. By ``invoking the class object'' I mean expressions such >> > as Class1() or Class2(). ``Class1'' represents the object that >> > represents the class 1. Since the syntax is that of procedure >> > invokation, I say ``invoking the class object''. >> >> An experiment. What's my definition of Stack? It's either Empty or >> Pair, so it's a union. So let us create two inner classes (that is, >> inner to Stack) and make them behave just like Empty and Pair. Using >> __new__(), we can produce a Stack object that is sometimes Empty() and >> sometimes Pair(...). >> > > The most straight-forward way to represent this concept in an > object-oriented way is subclassing. > > class Stack: > ... # put whatever code is common here > > class Empty(Stack): > ... # put Empty-specific code here, possibly overriding Stack methods > > class Pair(Stack): > ... # ditto, overriding or augmenting as needed > > This way, everything is an instance of Stack, but they are still > distinct types for when you need to distinguish. Can you provide a small example? I can't see what you mean, but it seems interesting. From PythonList at DancesWithMice.info Mon Oct 31 00:05:44 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 31 Oct 2022 17:05:44 +1300 Subject: Weired behaviour - The slice of empty string not return an error In-Reply-To: <CAMXb-5ngFYTgo=Y8CW3HbAt+xBTkJAi=4KN3-c0-jMAEUrn4Xg@mail.gmail.com> References: <CAMXb-5m_HPyTzeb0P=VmAUmTEE5ZjV9097N43eWOCK=3=kFwKA@mail.gmail.com> <CAMXb-5ngFYTgo=Y8CW3HbAt+xBTkJAi=4KN3-c0-jMAEUrn4Xg@mail.gmail.com> Message-ID: <0c27a5be-c99e-fdd8-8d4b-9f1595ce65b7@DancesWithMice.info> On 31/10/2022 03.59, Yassine Nasri wrote: > PS: The ''[::] should return an error logically. > > Le dim. 30 oct. 2022 ? 15:57, Yassine Nasri <yassine.naasri at gmail.com> a > ?crit : > >> Hello, >> >> len('') # => 0''[0] # => error''[::] # => ''''[::] # <=> ''[0:len(''):1] >> >> the syntax of slice: >> >> slice(start, end, step) >> >> The start in ''[::] equivalent at index 0 of the '' >> >> Since the index 0 of '' returns an error. >> >> The ''[::] should not return an error logically. Perhaps it will help to say: - "indexing" one "element" from a "sequence" will yield a single result of the type of that element - "slicing" a "sequence" will yield a result of the same type as the original sequence The corollary to the first is expected: that if there is no element at the stated index/position, something is wrong. However, what is not necessarily apparent, is that because the result is of the same type as the original sequence, and an empty-sequence is perfectly legal; so is it possible to slice something and receive back 'nothing'. The second 'saying' is to use the correct jargon: - in a[ i ] i is an "index" - in a[ i:j ] i and j are "parameters" A parameter does not (also) need to be a legal index! This is proven (as you have discovered (but is difficult to read, above): >>> sequence = [] >>> len( sequence ) 0 >>> sequence[ 0 ] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range >>> sequence[ 0:1 ] [] The question (and assertion) are discussed in the manual: ?Sequences These represent finite ordered sets indexed by non-negative numbers. The built-in function len() returns the number of items of a sequence. When the length of a sequence is n, the index set contains the numbers 0, 1, ?, n-1. Item i of sequence a is selected by a[i]. Sequences also support slicing: a[i:j] selects all items with index k such that i <= k < j. When used as an expression, a slice is a sequence of the same type. This implies that the index set is renumbered so that it starts at 0. Some sequences also support ?extended slicing? with a third ?step? parameter: a[i:j:k] selects all items of a with index x where x = i + n*k, n >= 0 and i <= x < j. ? Thus, an index must point to an existing element, whereas the parameters of a slice need not. If the slice-specification calls for elements 'beyond' the end of the sequence, then the result will only contain items up-to the last element, ie the length of the resultant-sequence will be shorter than j - i, where j > len( sequence ). # Proof (which concurs with the OP's observations) # playing with a tuple's indexes/indices >>> sequence = 1,2,3 >>> sequence[ 1 ] 2 # notice the result's type! >>> sequence[ 9 ] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: tuple index out of range # the above index is plainly 'beyond' len( sequence ) # do you know about negative indexes/indices? >>> sequence[ -1 ] 3 >>> sequence[ -9 ] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: tuple index out of range # again this index is 'beyond' the first element of the sequence # let's play with some slicing; >>> sequence[ 0:3 ] (1, 2, 3) >>> [ 1, 2, 3 ][ 0:3 ] [1, 2, 3] # same applies to lists (and strings, etc) # notice the types! >>> sequence[ 1:1 ] () >>> sequence[ 1:2 ] (2,) >>> sequence[ -1:2 ] () >>> sequence[ -1:-2 ] () >>> sequence[ -1:-2:-1 ] (3,) >>> sequence[ -1:-3:-1 ] (3, 2) # OK, what happens when parameters point to non-existent indexes? >>> sequence[ 1:9 ] (2, 3) >>> sequence[ 1:-9 ] () >>> sequence[ -1:-9:-1 ] (3, 2, 1) >>> sequence[ -9:-1:-1 ] () # yes, they are parameters and not strictly indexes/indices! https://docs.python.org/3/reference/datamodel.html?highlight=slicing#the-standard-type-hierarchy for "sequences" and "slice objects" Note that a Python set is "collection" but not a "sequence". Which means that neither indexing nor slicing (per above) will work on a set. We can ask if a particular value appears in a set ("contains") but cannot ask for the n-th element. To be able to index or slice it, a sequence must offer a __getitem__() method - tuple, list, and string do; but set does not. (check for yourself: help( set ) ) https://docs.python.org/3/library/collections.abc.html?highlight=collection -- Regards, =dn From rosuav at gmail.com Mon Oct 31 01:21:53 2022 From: rosuav at gmail.com (Chris Angelico) Date: Mon, 31 Oct 2022 16:21:53 +1100 Subject: an oop question In-Reply-To: <86v8o0hlno.fsf@yaxenu.org> References: <86y1sxmmvo.fsf@yaxenu.org> <unions-20221030153013@ram.dialup.fu-berlin.de> <86k04hmkf3.fsf@yaxenu.org> <86leoxi5i7.fsf@yaxenu.org> <CAPTjJmqibdNc+ehd7=Hc1w5ypHCpJpYjZd1_oMinHE6pu6Ax0Q@mail.gmail.com> <mailman.840.1667169075.20444.python-list@python.org> <86v8o0hlno.fsf@yaxenu.org> Message-ID: <CAPTjJmpa=FMqeidpZReL3NXjua8MdUHi4jPe_z6jUf_k+6s9VA@mail.gmail.com> On Mon, 31 Oct 2022 at 14:38, Julieta Shem <jshem at yaxenu.org> wrote: > > Chris Angelico <rosuav at gmail.com> writes: > > > The most straight-forward way to represent this concept in an > > object-oriented way is subclassing. > > > > class Stack: > > ... # put whatever code is common here > > > > class Empty(Stack): > > ... # put Empty-specific code here, possibly overriding Stack methods > > > > class Pair(Stack): > > ... # ditto, overriding or augmenting as needed > > > > This way, everything is an instance of Stack, but they are still > > distinct types for when you need to distinguish. > > Can you provide a small example? I can't see what you mean, but it > seems interesting. Sure. The easiest way would be to take your existing Empty and Pair classes, have them subclass Stack, and don't bother putting any code at all into Stack. Then construct an Empty and a few Pairs, and what you'll see is that all of them are also instances of Stack. After that, it's really a question of what you expect to be able to do with either an Empty or a Pair. Anything that should be possible with both types (that is, anything that should be possible with either variant of Stack) should get moved into the Stack type, while anything that is specific to one or the other stays in its own class. So here's a very very simple example: class Stack: def prepend(self, other): return Pair(other, self) class Empty(Stack): def is_last(self): return True def get_current(self): raise ValueError("Stack empty") def get_next(self): raise ValueError("Stack empty") class Pair(Stack): def __init__(self, item1, item2): self.item1 = item1 self.item2 = item2 def get_current(self): return self.item1 def get_next(self): return self.item2 def is_last(self): return isinstance(self.item2, Empty) With this setup, you can build a stack by prepending items onto an Empty endpoint, and can iterate over it with the get_current and get_next methods. (Making this actually iterable, so that it works with a Python 'for' loop, would be a good exercise.) In this example, there isn't much code in the Stack class. But you could easily add more, and it would apply to both Empty and Pair. ChrisA From learn2program at gmail.com Mon Oct 31 05:36:59 2022 From: learn2program at gmail.com (Alan Gauld) Date: Mon, 31 Oct 2022 09:36:59 +0000 Subject: an oop question In-Reply-To: <86y1sxmmvo.fsf@yaxenu.org> References: <86y1sxmmvo.fsf@yaxenu.org> Message-ID: <39be3c02-df6e-5aa3-2220-55c403aabc43@yahoo.co.uk> On 30/10/2022 14:01, Julieta Shem wrote: > I wrote the classes > > class Empty: > ... > class Pair: > ... > > (*) How to build a stack? > > These Lisp-like sequences are clearly a stack. That is a very important observation. A Pair IS-A Stack(sort of). If you had a stack you could create a Pair from it certainly. > So far so good, but when it comes to building a better user interface > for it I have no idea how to do it. I think one of the purposes of OOP > is to organize code hierarchically so that we can reuse what we wrote. One of the purposes of classes certainly. I'm not so sure it's a purpose of OOP. They are not the same thing. A class is a programming construct OOP is a programming style. Classes facilitate OOP but can be used outside of OOP too. > So I tried to make a Stack by inheriting Pair. But you said above that a Pair was a Stack. Inheritance implies an IS-A relationship, so Stack inheriting Pair would mean that a Stack was a Pair. That is not really true. A Stack could use a Pair (or many of them) but it is not a Pair. Trying to use inheritance inappropriately is one of the biggest (and commonest) mistakes in OOP. It invariably leads to complications. If in doubt use delegation instead. > class Stack(Pair): > pass > >>>> Stack(1, Empty()) > Stack(1, Empty()) > > Then I wrote pop and push. > >>>> Stack(1, Empty()).pop() > 1 > >>>> Stack(1, Empty()).push(2) > Stack(2, Stack(1, Empty())) > > So far so good. Now let me show you what I can't do. > > (*) The difficulty of encapsulating a union > > The Lisp-like sequences we're building here are union-like data > structures. A /sequence/ is either Empty() or Pair(..., /sequence/). I > have not found a way to represent this either-or datastructure with a > class. For example, there is no way right now to build an empty Stack > by invoking the Stack constructor. > >>>> Stack() > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: Pair.__init__() missing 2 required positional arguments: 'first' and 'rest' > The usual Python approach to such things is to put some default values(often None but could be an Empty instance in your case) in the init() method parameter list. Then test if the inputs are None and if so take the appropriate action. > class Pair: > def __init__(self, first=Empty(), rest=Empty()): Like this. > if not isinstance(rest, Pair) and not isinstance(rest, Empty): > raise ValueError("rest must be Empty or Pair") > self.first = first > self.rest = rest > def fromIterable(it): > if len(it) == 0: > return Empty() > else: > return Pair(it[0], Pair.fromIterable(it[1:])) > def __str__(self): > return "{}({!r}, {})".format(self.__class__.__name__, self.first, str(self.rest)) > def __repr__(self): > return str(self) > def __len__(self): > return 1 + self.rest.__len__() > > class Empty: > def __len__(self): > return 0 > def __str__(self): > return "Empty()" > def __repr__(self): > return self.__str__() > def __new__(clss): > if not hasattr(clss, "saved"): > clss.saved = super().__new__(clss) > return clss.saved > > class Stack(Pair): > def pop(self): > return self.first > def push(self, x): > return Stack(x, self) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From darkstone at o2online.de Mon Oct 31 14:10:45 2022 From: darkstone at o2online.de (darkstone at o2online.de) Date: Mon, 31 Oct 2022 18:10:45 +0000 Subject: =?utf-8?Q?Problems_with_IDLE_in_Windows_8.1_and_installer_x86_Version_3.1?= =?utf-8?Q?0.8?= Message-ID: <202210311822.29VIMTpw130438@mail92c50.megamailservers.eu> Dear Sir or Madam, i uninstalled this, because my Idle doesn?t start by clicking on the Icon. Are there any Solutions for the problem? Thanks, Andr? From eryksun at gmail.com Mon Oct 31 15:18:10 2022 From: eryksun at gmail.com (Eryk Sun) Date: Mon, 31 Oct 2022 14:18:10 -0500 Subject: Problems with IDLE in Windows 8.1 and installer x86 Version 3.10.8 In-Reply-To: <202210311822.29VIMTpw130438@mail92c50.megamailservers.eu> References: <202210311822.29VIMTpw130438@mail92c50.megamailservers.eu> Message-ID: <CACL+1atsgNQkJ7EDD33aw2y8iCHO-iwVdVWy69o3QEj591sBYw@mail.gmail.com> On 10/31/22, darkstone at o2online.de <darkstone at o2online.de> wrote: > > i uninstalled this, because my Idle doesn?t start by clicking on the Icon. > Are there any Solutions for the problem? If it's the standard distribution from python.org, run the installer again, and ensure that the test suite is installed. In 3.10.8, IDLE mistakenly depends on the test suite. This mistake is fixed in 3.10.9, which is planned to be released in early December. From PythonList at DancesWithMice.info Mon Oct 31 15:23:19 2022 From: PythonList at DancesWithMice.info (dn) Date: Tue, 1 Nov 2022 08:23:19 +1300 Subject: Fwd: A typing question In-Reply-To: <English-20221031135425@ram.dialup.fu-berlin.de> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <mailman.833.1667125619.20444.python-list@python.org> <tjma3i$gqh$1@gioia.aioe.org> <lose-20221030180606@ram.dialup.fu-berlin.de> <41e045af-c35a-6012-9a1a-aa2e6e4c4bfc@DancesWithMice.info> <CAPTjJmqAWvZdXzYAzm-OcxsDL0ta-4fCY5GHzG+pdErx6qOEkg@mail.gmail.com> <c2dabfc0-a931-bde6-59a1-ba337a442ca7@DancesWithMice.info> <mailman.844.1667177414.20444.python-list@python.org> <English-20221031135425@ram.dialup.fu-berlin.de> Message-ID: <c18d3a41-ca13-6999-6056-82d4baaa0c0e@DancesWithMice.info> On 01/11/2022 01.56, Stefan Ram wrote: > dn <PythonList at DancesWithMice.info> writes: >> On 31/10/2022 11.44, Chris Angelico wrote: > ... >>> I'm curious to what extent sloppy English correlates with sloppy code. > ... >> When it comes to CVs/resum?s (see what I did there?), I must admit that >> the most egregious of errors in spelling or grammar do ensure that an >> applicant's 'work' is quickly routed to "file 13" (an American-English >> term, many other English-speakers will not have heard previously). > > This discussion reminds me of something Eric Raymond said: > > |While sloppy writing does not invariably mean sloppy thinking, > |we've generally found the correlation to be strong -- and we > |have no use for sloppy thinkers. If you can't yet write > |competently, learn to. > Eric Raymond > > . Other relevant quotations are: > > |Besides a mathematical inclination, an exceptionally good > |mastery of one's native tongue is the most vital asset of a > |competent programmer. > Edsgar Dijkstra > > |I've found that some of the best [Software ]developers > |of all are English majors. They'll often graduate with > |no programming experience at all, and certainly without > |a clue about the difference between DRAM and EPROM. > | > |But they can write. That's the art of conveying > |information concisely and clearly. Software development > |and writing are both the art of knowing what you're going > |to do, and then lucidly expressing your ideas. > | > Jack Ganssle > > |The narrative measures of conjunction use, event > |content, perspective shift, and mental state reference > |were significantly predictive of later Math scores. > "Evidence of a Relation between Early Narrative and ..." (2004) > - DK O?Neill > > |I have never, ever, ever seen a great software developer > |who does not have amazing attention to detail. > (2006-08-20) - Rob Walling +1 Thanks for these! -- Regards, =dn From hjp-python at hjp.at Mon Oct 31 17:08:46 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 31 Oct 2022 22:08:46 +0100 Subject: Fwd: A typing question In-Reply-To: <20221030102656.jwpzorowcuqnirlt@hjp.at> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> Message-ID: <20221031210846.24qunvsr465vid7w@hjp.at> On 2022-10-30 11:26:56 +0100, Peter J. Holzer wrote: > On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: > > The funny thing is that if I replace foos by Foos it works because it gets > > known by the initial initialization :-) ! > > > > ________________________ > > from typing import List, Optional > > > > class GLOBALS: > > Foos: Optional[Foos]=None > [...] > > class Foos: > > That seems like a bug to me. But is it even true? I just tried to reproduce it (should have done that before answering) with mypy 0.942 (included in Ubuntu 22.04 LTS): ----[p1]--------------------------------------------------------------- from typing import List, Optional class GLOBALS: foos: Optional[Foos]=None class Foo: def __init__(self): pass class Foos: Foos: List[Foo]=[] # SOME GLOBALS ARE USED HERE def __init__(self): pass GLOBALS.foos=Foos() ----------------------------------------------------------------------- ----[p2]--------------------------------------------------------------- from typing import List, Optional class GLOBALS: Foos: Optional[Foos]=None class Foo: def __init__(self): pass class Foos: Foos: List[Foo]=[] # SOME GLOBALS ARE USED HERE def __init__(self): pass GLOBALS.Foos=Foos() ----------------------------------------------------------------------- --- p1 2022-10-31 21:59:49.639869922 +0100 +++ p2 2022-10-31 21:58:19.815830677 +0100 @@ -1,7 +1,7 @@ from typing import List, Optional class GLOBALS: - foos: Optional[Foos]=None + Foos: Optional[Foos]=None class Foo: @@ -15,4 +15,4 @@ def __init__(self): pass -GLOBALS.foos=Foos() +GLOBALS.Foos=Foos() So the only difference is the capitalization of foos. And mypy accepts both (as it probably should): % mypy p1 Success: no issues found in 1 source file % mypy p2 Success: no issues found in 1 source file If you did something different, please explain what you did. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221031/067ed646/attachment.sig> From elasstiika at gmail.com Mon Oct 31 17:09:26 2022 From: elasstiika at gmail.com (elas tica) Date: Mon, 31 Oct 2022 14:09:26 -0700 (PDT) Subject: Operator: inappropriate wording? In-Reply-To: <mailman.817.1666815158.20444.python-list@python.org> References: <AQHY6XGnHcGPspB8wk2kN80qpezk0a4hGtO5> <SA1PR14MB585507DE975BB911C3EF165AB9309@SA1PR14MB5855.namprd14.prod.outlook.com> <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> <mailman.817.1666815158.20444.python-list@python.org> Message-ID: <91181647-7008-4912-86a2-e6f39cda4744n@googlegroups.com> Le mercredi 26 octobre 2022 ? 22:12:59 UTC+2, Weatherby,Gerard a ecrit?: > No. If the docs say in one place a comma is not an operator, they shouldn?t call it an operator in another place. > > I?ve submitted a pull request https://github.com/python/cpython/pull/98736 -- we?ll have to see what The Powers That Be think. Thanks for the (merged) pull request about the "comma operator"! I return to the last two quotes in the Reference Document regarding these so-called "assignment operators". The entry in the glossary explains that the comma symbol is not an operator. Well, I just realized that this same entry also explains that the = symbol is not an operator, as you can see by reading the end of their response: The same is true of the various assignment operators (=, += etc). They are not truly operators but syntactic delimiters in assignment statements. (glossary entry link: https://docs.python.org/3/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence) Talking about an assignment operator in Python is even more confusing because, since Python 3.8, there is a real assignment operator, namely the walrus operator. As explained above, the correct expression would be "assignement delimiter" or "assignement statement" or "assignement symbol". By the way, Alex Martelli shares this view, explaining: The "=" operator in Python ... doesn't exist, since '=' is not an operator in Python (just like it isn't, say, in VB). But, OK, you mean "assignment". (source: https://groups.google.com/g/comp.lang.python/c/K6HfK6HANR4/m/OG9QBzFmTR8J) From hjp-python at hjp.at Mon Oct 31 17:15:47 2022 From: hjp-python at hjp.at (Peter J. Holzer) Date: Mon, 31 Oct 2022 22:15:47 +0100 Subject: Fwd: A typing question In-Reply-To: <f26d3410-f4dc-095a-33b5-28c7a9cc43db@web.de> References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <557d6b4c-c5f7-f2f0-8bc7-5582ebfbac47@tompassin.net> <20221030133729.3rls5molew7eya5n@hjp.at> <f26d3410-f4dc-095a-33b5-28c7a9cc43db@web.de> Message-ID: <20221031211547.hwphgcnzoszcll3l@hjp.at> On 2022-10-30 20:43:23 +0100, Peter Otten wrote: > On 30/10/2022 14:37, Peter J. Holzer wrote: > > On 2022-10-30 09:23:27 -0400, Thomas Passin wrote: > > > On 10/30/2022 6:26 AM, Peter J. Holzer wrote: > > > > On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: > > > > > The funny thing is that if I replace foos by Foos it works because it gets > > > > > known by the initial initialization :-) ! [...] > > > > Yes. I was referring to the code as written. Why does that work? I don't > > think it should. > > For me it makes sense. I think mypy should refrain from trying to figure > out order of execution. I was unclear, sorry. What I meant was "why does replacing foos by Foos make the error disappear?" not "why do forward references work?". But may have misunderstood what Paulo meant as I cannot reproduce his results. So maybe the behaviour I don't understand (and would consider buggy) doesn't actually exist. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp at hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <https://mail.python.org/pipermail/python-list/attachments/20221031/f56137b8/attachment.sig> From rosuav at gmail.com Mon Oct 31 17:18:23 2022 From: rosuav at gmail.com (Chris Angelico) Date: Tue, 1 Nov 2022 08:18:23 +1100 Subject: Operator: inappropriate wording? In-Reply-To: <91181647-7008-4912-86a2-e6f39cda4744n@googlegroups.com> References: <SA1PR14MB585507DE975BB911C3EF165AB9309@SA1PR14MB5855.namprd14.prod.outlook.com> <4a3bbb16-0d2e-4230-948d-793e5915721an@googlegroups.com> <mailman.817.1666815158.20444.python-list@python.org> <91181647-7008-4912-86a2-e6f39cda4744n@googlegroups.com> Message-ID: <CAPTjJmo=PopQ_D+Q8tbHbZKoT4g9vitwNSf3YQ3mum1NcS3EgA@mail.gmail.com> On Tue, 1 Nov 2022 at 08:15, elas tica <elasstiika at gmail.com> wrote: > > Le mercredi 26 octobre 2022 ? 22:12:59 UTC+2, Weatherby,Gerard a ecrit : > > No. If the docs say in one place a comma is not an operator, they shouldn?t call it an operator in another place. > > > > I?ve submitted a pull request https://github.com/python/cpython/pull/98736 -- we?ll have to see what The Powers That Be think. > > > Thanks for the (merged) pull request about the "comma operator"! > > I return to the last two quotes in the Reference Document regarding these so-called "assignment operators". > > The entry in the glossary explains that the comma symbol is not an operator. Well, I just realized that this same entry also explains that the = symbol is not an operator, as you can see by reading the end of their response: > > The same is true of the various assignment operators (=, += etc). They are not truly operators but syntactic delimiters in assignment statements. > > (glossary entry link: https://docs.python.org/3/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence) > > Talking about an assignment operator in Python is even more confusing because, since Python 3.8, there is a real assignment operator, namely the walrus operator. As explained above, the correct expression would be "assignement delimiter" or "assignement statement" or "assignement symbol". > Wording is hard. Just ask the SQL standard whether NULL is a value. ChrisA From eryksun at gmail.com Mon Oct 31 18:00:10 2022 From: eryksun at gmail.com (Eryk Sun) Date: Mon, 31 Oct 2022 17:00:10 -0500 Subject: Problems with IDLE in Windows 8.1 and installer x86 Version 3.10.8 In-Reply-To: <202210312138.29VLcBUQ008124@mail118c50.megamailservers.eu> References: <202210311822.29VIMTpw130438@mail92c50.megamailservers.eu> <CACL+1atsgNQkJ7EDD33aw2y8iCHO-iwVdVWy69o3QEj591sBYw@mail.gmail.com> <202210312138.29VLcBUQ008124@mail118c50.megamailservers.eu> Message-ID: <CACL+1asuVG++KH45JEWM6FyRP0tduv1695WHHMfUKFyFocO8yQ@mail.gmail.com> On 10/31/22, darkstone at o2online.de <darkstone at o2online.de> wrote: > > I installed the Standard Distribution from python.org again, and i ensured, > that the checkmark test Suite is enabled. Idle does?nt start. The installer > says ?Installation successfully? at the end. > > What went wrong and how can I further delimit the fault/find the error? Open a command prompt and run the following command: py -3.10-32 -m idlelib If it fails, an exception and traceback should be printed to the console. From p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt Mon Oct 31 22:04:47 2022 From: p_d_a_s_i_l_v_a_ns at nonetnoaddress.pt (Paulo da Silva) Date: Tue, 1 Nov 2022 02:04:47 +0000 Subject: Fwd: A typing question References: <tjjorc$dc7$1@gioia.aioe.org> <CAD+b3HgEoAkGq3o88Qo8HkB=6WbBU9Ae+4uqEYGVOCuS0U8dqw@mail.gmail.com> <CAD+b3Hh206TqYhwZb-tNG5phE=19QWn1cmZV60mgbSTpOB-hKw@mail.gmail.com> <1319deed-0f11-27ee-3cdf-a6012ced8438@DancesWithMice.info> <mailman.826.1667079303.20444.python-list@python.org> <tjkb91$1mid$1@gioia.aioe.org> <20221030102656.jwpzorowcuqnirlt@hjp.at> <20221031210846.24qunvsr465vid7w@hjp.at> <mailman.853.1667250535.20444.python-list@python.org> Message-ID: <tjpus1$1rrj$1@gioia.aioe.org> ?s 21:08 de 31/10/22, Peter J. Holzer escreveu: > On 2022-10-30 11:26:56 +0100, Peter J. Holzer wrote: >> On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote: >>> The funny thing is that if I replace foos by Foos it works because it gets >>> known by the initial initialization :-) ! >>> >>> ________________________ >>> from typing import List, Optional >>> >>> class GLOBALS: >>> Foos: Optional[Foos]=None >> [...] >>> class Foos: >> >> That seems like a bug to me. > > But is it even true? > > I just tried to reproduce it (should have done that before answering) > with mypy 0.942 (included in Ubuntu 22.04 LTS): > > ----[p1]--------------------------------------------------------------- > from typing import List, Optional > > class GLOBALS: > foos: Optional[Foos]=None > > class Foo: > > def __init__(self): > pass > > class Foos: > Foos: List[Foo]=[] > # SOME GLOBALS ARE USED HERE > > def __init__(self): > pass > > GLOBALS.foos=Foos() > ----------------------------------------------------------------------- > > ----[p2]--------------------------------------------------------------- > from typing import List, Optional > > class GLOBALS: > Foos: Optional[Foos]=None > > class Foo: > > def __init__(self): > pass > > class Foos: > Foos: List[Foo]=[] > # SOME GLOBALS ARE USED HERE > > def __init__(self): > pass > > GLOBALS.Foos=Foos() > ----------------------------------------------------------------------- > > --- p1 2022-10-31 21:59:49.639869922 +0100 > +++ p2 2022-10-31 21:58:19.815830677 +0100 > @@ -1,7 +1,7 @@ > from typing import List, Optional > > class GLOBALS: > - foos: Optional[Foos]=None > + Foos: Optional[Foos]=None > > class Foo: > > @@ -15,4 +15,4 @@ > def __init__(self): > pass > > -GLOBALS.foos=Foos() > +GLOBALS.Foos=Foos() > > So the only difference is the capitalization of foos. And mypy accepts > both (as it probably should): > > % mypy p1 > Success: no issues found in 1 source file > % mypy p2 > Success: no issues found in 1 source file > > > If you did something different, please explain what you did. Yes for mypy. Try to run them (python3 <your script name>). Paulo