Re: Fast lookup of bulky "table"

2023-01-15 Thread dn via Python-list

On 16/01/2023 08.36, Weatherby,Gerard wrote:

I think any peformance improvements would have to come from a language change 
or better indexing of the data.


Exactly!

Expanding on @Peter's post: databases (relational or not) are best 
organised according to use. Some must accept rapid insert/updates. 
Others are about look-ups (data-retrieval).


A basic RDBMS, just as a Python dict, may only offer a single key for 
efficient retrieval.


Postgres and MySQL (for example) enable the establishment of multiple 
and sophisticated indices/indexes, and the aptly-named "views" of data.


If the queries can be grouped according to the manner in which the data 
must be accessed, a view could be built for each. At which time, even if 
every row must be accessed, the retrieval will be made more efficient 
and/or the response better-organised.


Thus, if we have a DB of people. Many retrievals are likely to utilise 
an index on 'name'. However, if at times interest is limited to place or 
suburb, an index and view of such will speed things from O(n). 
Similarly, if a query is only to return people with a dog license.


Some programmers don't realise that SQL can also be used for 
calculations, eg the eponymous COUNT(), which saves (CPU-time and 
coding-effort) over post-processing in Python.


If there are many way to group/examine the data, then this may not be 
possible, but that depends upon the count of views cf the value of 
speedy-response - and bearing-in-mind that the demands for response-time 
may vary by type of query/data-access.


So many variables to consider ...

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Improvement to imports, what is a better way ?

2023-01-18 Thread dn via Python-list

On 19/01/2023 08.56, Mats Wichmann wrote:

On 1/18/23 12:29, Paul Bryan wrote:

...


import os as    os
import sys as   sys
import importlib as importlib


A general comment: there are some very common "import ... as" idioms 
(for example, it seems like *everyone* does "import pandas as pd") and 
those are okay to follow, but in general I would stay away from trying 
to give everything short-names.  Each module imported with a name other 
than their own is a memory burden for the reader (maybe even for you!).



import aboutTime as tt  # Time dates timestamps and the
like
import avMedia as   av  # Audio and maybe video 'someday'
well definitely lots of TTS text to speech
import basicSwitchboard as  sc  # First switchboard lurking.
Kickoff to sequence viewers


Any decent editor these days will autocomplete for you, so there's 
really not much if any typing burden in using the full names.


Have vacillated on aspects of this topic, over the years. Currently I'm 
in favor of abbreviations and not only the commonly-accepted/-used ones, 
eg np for numpy.

(but am keen to learn from your wisdom)

I've argued the auto-complete cf typing point. So, that not at-issue.

The longer an identifier, the more it 'pushes' code over to the right or 
to expand over multiple screen-lines. Some thoughts on this are behind 
PEP-008 philosophies, eg line-limit.


In the body of the code, if every time an external identifier is used it 
must be prefixed by a full 'path', the cognitive "burden" shifts from 
the aspect highlighted (above), to a reading-burden. Thus, (in extreme 
cases) moving towards a 'wall of text' problem.


The primary interest is to remove "burden" aka complexity.

In using TDD, code is constructed module-by-module (not necessarily a 
Python Module). So, when it comes time to call avMedia.fetch_the_file() 
[sic] there is little thinking about the "avMedia" bit. The emphasis is 
on the function-name, and it's parameters. 'I need that file so that I 
can ...'.


Using the IDE-as-a-tool argument (similar to above): if I miss-out, 
mistype, use the wrong abbreviation, or otherwise fail to identify where 
fetch_the_file() is located, the IDE will immediately tell me.

(dn you're wrong - again!)

Accordingly, the abbreviation/full-module-name is almost taken-on-trust. 
(you're going to prove/test the linkage, either way, right?)



Personal Biases:
- TDD
- when starting to write the program[me]-code one of the first steps is 
to marshal resources, which includes the question: which functions will 
be called and thus which Python-modules should be imported? Thus, 
listing all imports 'at the top' is a separable task.
- an early language learned (back-when) was COBOL, which has a formal 
structure and separation between elements/phases of a program[me]'s 
construction and execution. Some such thinking no doubt lingers...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: evaluation question

2023-01-27 Thread dn via Python-list

On 28/01/2023 05.37, mutt...@dastardlyhq.com wrote:

This is probably a dumb newbie question but I've just started to learn
python3 and eval() isn't behaving as I'd expect in that it works for
some things and not others. eg:


eval("1+1")

2

eval("print(123)")

123

eval("for i in range(1,10): i")

Traceback (most recent call last):
   File "", line 1, in 
   File "", line 1
 for i in range(1,10): i
   ^
SyntaxError: invalid syntax

Why did the 3rd one fail? Does it not handle complex expressions?


eval() is very powerful, and therefore rather dangerous in the risks it 
presents.


Thus, seems a strange/advanced question for a "newbie" to be asking. YMMV!

Do you know about the Python REPL?

If you open python within a terminal, each of the three 
expressions/compound-statements listed will work, as desired, without 
eval().


dn $ ... python
Python 3.11.1 (main, Jan  6 2023, 00:00:00) [GCC 12.2.1 20221121 (Red 
Hat 12.2.1-4)] on linux

Type "help", "copyright", "credits" or "license" for more information.
>>> 1+1
2
>>> print( 123 )
123
>>> for i in range( 1, 10 ): i
...
1
2
3
4
5
6
7
8
9
>>> exit()

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: logically Boolean

2023-01-28 Thread dn via Python-list

On 29/01/2023 09.28, Chris Angelico wrote:

The REAL boolean is the friends we made along the way?

By REAL did you mean float - True or False?


(for the FORTRAN-free: https://fortranwiki.org/fortran/show/real)

--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: evaluation question

2023-01-31 Thread dn via Python-list

On 01/02/2023 11.59, Greg Ewing wrote:

On 31/01/23 10:24 pm, mutt...@dastardlyhq.com wrote:
All languages have their ugly corners due to initial design mistakes 
and/or

constraints. Eg: java with the special behaviour of its string class, C++
with "=0" pure virtual declaration. But they don't dump them and make 
all old

code suddenly cease to execute.


No, but it was decided that Python 3 would have to be backwards
incompatible, mainly to sort out the Unicode mess. Given that,
the opportunity was taken to clean up some other mistakes as well.


+1
and the move to Unicode has opened-up the Python community beyond the 
US, to embrace 'the world' - a proposition (still) not well-recognised 
by (only) English-speakers/writers/readers.



Even though the proposition has a troll-bait smell to it:-

1 nothing "ceased to execute" and Python 2 was maintained and developed 
for quite some time and in-parallel to many Python 3 releases.


2 the only constant in this business is 'change'. I'd rather cope with 
an evolution in this language (which we know and love), than one day 
realise that it has become dated or inflexible, and have to learn a new, 
replacement, language!


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Organizing modules and their code

2023-02-03 Thread dn via Python-list

On 04/02/2023 16.24, Thomas Passin wrote:

On 2/3/2023 5:14 PM, 2qdxy4rzwzuui...@potatochowder.com wrote:

Keep It Simple:  Put all four modules at the top level, and run with it
until you falsify it.  Yes, I would give you that same advice no matter
what language you're using.


In my recent message I supported DESIGN 1.  But I really don't care much 
about the directory organization.  It's designing modules whose business 
is to handle various kinds of operations that counts, not so much the 
actual directory organization.


+1 (and to comments made in preceding post)

With ETL the 'reasons to change' (SRP) come from different 'actors'. For 
example, the data-source may be altered either in format or by changing 
the tool you'll utilise to access. Accordingly, the virtue of keeping it 
separate from other parts. If you have multiple data-sources, then each 
should be separate for the same reason.


The transform is likely dictated by your client's specification. So, 
another separation. Hence Design 1.


There is a strong argument for suggesting that we're going out of our 
way to imagine problems or future-changes (which may never happen). If 
this is (definitely?) a one-off, then why-bother? If permanence is 
likely, (so many 'temporary' solutions end-up lasting years!) then 
re-use can?should be considered.


Thus, when it comes to loading the data into your own DB; perhaps this 
should be separate, because it is highly likely that the mechanisms you 
build for loading will be matched by at least one 'someone else' wanting 
to access the same data for the desired end-purposes. Accordingly, a 
shareable module and/or class for that.



We can't see the code-structure, so some of the other parts of your 
question(s) are too broad. Here's hoping you and Liskov have a good time 
together...



My preference is for (what I term) the 'circles' diagram (see copy at 
https://mahu.rangi.cloud/CraftingSoftware/CleanArchitecture.jpg). This 
illustrates the 'rule' that code handling the inner functionality not 
know what happens at the more detailed/lower-level functional level of 
the outer rings.


With ETL, there's precious little to embody various circles, but the 
content of the outer ring is obvious. The "T" rules comprise the inner 
"Use Case", even if you eschew "Entities" insofar as OOP-avoidance is 
concerned. This 'inversion', where the inner controls don't need to care 
about the details of outer-ring implementation (is it an RDBMS, MySQL or 
Postgres; or is it some NoSQL system?) brings to life the "D" of SOLID, 
ie Dependency Inversion.



You may pick-up some ideas or reassurance from "Making a Simple Data 
Pipeline Part 1: The ETL Pattern" 
(https://www.codeproject.com/Articles/5324207/Making-a-Simple-Data-Pipeline-Part-1-The-ETL-Patte).


Let us know how it turns-out...
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Typing Number, PyCharm

2023-02-04 Thread dn via Python-list

Do we have a typing type-hint for numbers yet?


Often wanting to combine int and float, discovered that an application 
was doing a walk-through with/for uses three numeric types. Was 
intrigued to note variance, in that the code-set features two different 
methods for typing, in this situation:


def func( value ):
...using value...

where value may be an integer, a floating-point value, or a 
complex-number (but not decimal-type).

NB code snippets from memory (cf copy-paste)


Method 1 (possibly older code):-

from typing import Union
...
def fun( value:Union[ int, float, complex ] ):


Method 2:-

def fun( value:int|float|complex  ):


Pondering this, realised could use an alias to de-clutter the 
function-definition/signature:


Method 3:-

number_type = int|float|complex
...
def fun( value:number_type  ):


If it was important to have type consistency within the union, eg 
argument and return, could go for:


Method 4:-

from typing import TypeVar
number_type = TypeVar( 'number_type', int, float, complex )
...
def fun( value:number_type  ):


Then remembered the way we'd code an execution-time check for this using 
isinstance():


Method 5:-

from numbers import Number
...
def fun( value:Number  ):


Each of these will execute correctly.

All cause PyCharm to object if I try to call the fun(ction) with a 
string parameter - and execute an exception, as expected.



Accepting all the others, am curious as to why PyCharm objects to Method 
5 with "Expected type 'SupportsFloat | SupportsComplex | complex | 
SupportsIndex', got 'Number' instead? - yet still highlights the 
erroneous string parameter but none of the 'legal' data-types?


As soon as a list (in this case types) reaches three, my aged-eyes start 
to think de-cluttering is a good idea!


Do you know of another way to attack this/more properly?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Typing Number, PyCharm

2023-02-05 Thread dn via Python-list
No @Gerard, YOU weren't missing anything: since posting, have upgraded 
PyCharm to 2022.3.2 and the complaints about 'Method 5' have 
disappeared. Evidently a PyCharm issue!


Which alters the top-line question to: is numbers.Number the preferred 
type-hint when multiple numeric types are to be accepted?


PS no Decimal(s) nor Fraction(s) in my situation, but may be worth 
adding to a wider discussion...



On 06/02/2023 04.03, Weatherby,Gerard wrote:

dn,

I’m missing something here. Method 5 seems to work fine in PyCharm. I’m 
interpreting your statement as:


from fractions import Fraction
from numbers import Number


def double(value: Number):
if isinstance(value, Number):
/# noinspection PyTypeChecker
/return 2 * value
raise ValueError(f"{value}of {type(value)}is not a Number")


print(double(7))
print(double(7.2))
print(double(complex(3.2, 4.5)))
print(double(Fraction(7, 8)))
/# print(double("7")) PyCharm properly complains/

*From: *Python-list  
on behalf of dn via Python-list 

*Date: *Saturday, February 4, 2023 at 9:32 PM
*To: *'Python' 
*Subject: *Typing Number, PyCharm

*** Attention: This is an external email. Use caution responding, 
opening attachments or clicking on links. ***


Do we have a typing type-hint for numbers yet?


Often wanting to combine int and float, discovered that an application
was doing a walk-through with/for uses three numeric types. Was
intrigued to note variance, in that the code-set features two different
methods for typing, in this situation:

def func( value ):
  ...using value...

where value may be an integer, a floating-point value, or a
complex-number (but not decimal-type).
NB code snippets from memory (cf copy-paste)


Method 1 (possibly older code):-

from typing import Union
...
def fun( value:Union[ int, float, complex ] ):


Method 2:-

def fun( value:int|float|complex  ):


Pondering this, realised could use an alias to de-clutter the
function-definition/signature:

Method 3:-

number_type = int|float|complex
...
def fun( value:number_type  ):


If it was important to have type consistency within the union, eg
argument and return, could go for:

Method 4:-

from typing import TypeVar
number_type = TypeVar( 'number_type', int, float, complex )
...
def fun( value:number_type  ):


Then remembered the way we'd code an execution-time check for this using
isinstance():

Method 5:-

from numbers import Number
...
def fun( value:Number  ):


Each of these will execute correctly.

All cause PyCharm to object if I try to call the fun(ction) with a
string parameter - and execute an exception, as expected.


Accepting all the others, am curious as to why PyCharm objects to Method
5 with "Expected type 'SupportsFloat | SupportsComplex | complex |
SupportsIndex', got 'Number' instead? - yet still highlights the
erroneous string parameter but none of the 'legal' data-types?

As soon as a list (in this case types) reaches three, my aged-eyes start
to think de-cluttering is a good idea!

Do you know of another way to attack this/more properly?

--
Regards,
=dn
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$
 
<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$>



--
Regards,
=dn

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


Re: Line continuation and comments

2023-02-23 Thread dn via Python-list

On 22/02/2023 21.49, Robert Latest via Python-list wrote:

I found myself building a complicated logical condition with many ands and ors
which I made more manageable by putting the various terms on individual lines
and breaking them with the "\" line continuation character. In this context it
would have been nice to be able to add comments to lines terms which of course
isn't possible because the backslash must be the last character on the line.

Question: If the Python syntax were changed to allow comments after line-ending
backslashes, would it break any existing code? I can't think of an example.


Alternative to suggestions thus far: break the complex* logical 
condition into 'labelled' components, and then combine those (likely 
shorter) into the condition:


if person.is_adult and person.is_qualified and person.has_funds ...

which presumes that at some previous time we have, for example:

def is_adult( self )->bool:
return 21 <= self.age <= 65

(not that I'd like to see those two 'magic-constants' in anyone's code, 
but (hopefully) the idea has been conveyed...)



* "simple is better than..."

NB my PyCharm-settings grumble whenever I create an identifier which is 
only used once (and perhaps, soon after it was established). I 
understand the (space) optimisation, but prefer to trade that for 
'readability'.

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Line continuation and comments

2023-02-23 Thread dn via Python-list

On 24/02/2023 12.45, Weatherby,Gerard wrote:

“
NB my PyCharm-settings grumble whenever I create an identifier which is
only used once (and perhaps, soon after it was established). I
understand the (space) optimisation, but prefer to trade that for
'readability'.
“

I haven’t seen that one. What I get is warnings about:

def is_adult( self )->bool:
     LEGAL_AGE_US = 21
     return LEGAL_AGE

It doesn’t like LEGAL_AGE_US being all caps if declared in a function.


Yes, I suffered this one too.

The rationale comes from PEP-008 (Constants):

Constants are usually defined on a module level and written in all 
capital letters with underscores separating words.



Today, I wasn't criticised for:

NB my PyCharm-settings grumble whenever I create an identifier which is
only used once (and perhaps, soon after it was established). I
understand the (space) optimisation, but prefer to trade that for
'readability'.


Perhaps that came from AWS CodeWhisperer which I have since abandoned, 
or maybe from SonarLint (which I've just checked to discover it is not 
working properly...)


--
Regards,
=dn

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


Re: Why doesn't Python (error msg) tell me WHAT the actual (arg) values are ?

2023-02-23 Thread dn via Python-list

On 23/02/2023 09.05, Hen Hanna wrote:


   >  py   bug.py
Traceback (most recent call last):
  File "C:\Usenet\bug.py", line 5, in 
  print( a + 12 )
   TypeError: can only concatenate str (not "int") to str


Why doesn't  Python (error msg) do the obvious thing and tell me
 WHAT   the actual   (offending,  arg)  values are ?

In many cases, it'd help to know what string the var  A  had  ,   when the 
error occurred.
    i wouldn't have to put  print(a) just 
above,  to see.


In some ways, providing this information seems appropriate. Curiously, 
this does not even occur during an assert exception - despite the 
value/relationship being the whole point of using the command!


x = 1
assert x == 2

AssertionError (and that's it)

Then again, remember that exceptions can be 'caught'. So, such data 
would need to be added to the exception-instance. This could become 
quite costly.




What are the appropriate tools for the job?


Don't add an extra print(), use a debugger.

Not only does this allow you to breakpoint critical points in the code, 
but identifiers can be watch-ed and changes noted. The other handy 
feature is being able to correct the current erroneous value of the 
identifier and continue execution.


For us, memory-challenged coders, there is no need to remember to remove 
the print() again, afterwards.



The TypeError indicates a problem between the programmer's ears. What 
was thought to be a string or an integer was the opposite. This seems to 
be playing fast-and-loose with Python's dynamic-typing. To quote: "we're 
all adults here". Thus, I wouldn't recommend 're-cycling' an identifier 
to represent two different (types of) data-point in the same code - but 
there's nothing to stop you/anyone!


The other possibility is that it was an accident. Sounds more like 
something I would do, but... In this case, the tool which is your/my 
friend is typing. The IDE should catch most of the situations where an 
int would be used as an str, or v-v. Remember though, Python's typing is 
(a) not part of the language, and (b) probably won't help at run-time.



PS are you aware that there is a Python-Tutor list for the use of people 
learning Python?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Why doesn't Python (error msg) tell me WHAT the actual (arg) values are ?

2023-02-24 Thread dn via Python-list

On 25/02/2023 08.12, Peter J. Holzer wrote:

On 2023-02-24 16:12:10 +1300, dn via Python-list wrote:

In some ways, providing this information seems appropriate. Curiously, this
does not even occur during an assert exception - despite the
value/relationship being the whole point of using the command!

 x = 1
 assert x == 2

AssertionError (and that's it)


Pytest is great there. If an assertion in a test case fails it analyzes
the expression to give you various levels of details:

 test session starts 

platform linux -- Python 3.10.6, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
rootdir: /home/hjp/tmp/t
plugins: cov-3.0.0, anyio-3.6.1
collected 1 item

test_a.py F 
  [100%]

= FAILURES 
==
__ test_a 
___

 def test_a():
 a = [1, 2, 3]
 b = {"a": a, "b": 2}


   assert len(a) == len(b)

E   AssertionError: assert 3 == 2
E+  where 3 = len([1, 2, 3])
E+  and   2 = len({'a': [1, 2, 3], 'b': 2})

test_a.py:7: AssertionError
== short test summary info 
==
FAILED test_a.py::test_a - AssertionError: assert 3 == 2
= 1 failed in 0.09s 
=


+1
and hence the tone of slight surprise in the observation - because only 
ever use assert within pytests, and as observed, pytest amplifies the 
report-back to provide actionable-intelligence. See also: earlier 
contribution about using a debugger.



That said, have observed coders 'graduating' from other languages, 
making wider use of assert - assumed to be more data (value) 
sanity-checks than typing, but ...


Do you use assert frequently?


The OP seems wedded to his?her ways, complaining that Python does not 
work the way it 'should'. In turn, gives rise to the impression that 
expounding the advantages of TDD, and thus anticipating such unit and 
integration error-possibilities, might be considered an insult or unhelpful.

(sigh!)

Personally, I struggled a bit to adapt from the more-strictured (if not 
more-structured) languages of my past, to Python - particularly the 
different philosophies or emphases of what happens at 'compile-time' cf 
'execution-time'; and how such required marked changes in attitudes to 
design, time-allocation, work-flow, and tool-set. Two related-activities 
which made the language-change more workable and unleashed greater than 
step-change advantage, were: increased use of TDD, and actively learning 
the facilities within Python-oriented IDEs.


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Line continuation and comments

2023-02-24 Thread dn via Python-list

On 25/02/2023 10.04, Mark Bourne wrote:
Personally, I don't particularly like the way you have to put multiline 
strings on the far left (rather than aligned with the rest of the scope) 
to avoid getting spaces at the beginning of each line.  I find it makes 
it more difficult to see where the scope of the class/method/etc. 
actually ends, especially if there are multiple such strings.  It's not 
too bad for strings defined at the module level (outer scope) though, 
and of course for docstrings the extra spaces at the beginning of each 
line don't matter.


However, rather than using "+" to join strings as in your examples 
(which, as you suggest, is probably less efficient), I tend to use 
string literal concatenation which I gather is more efficient (treated 
as a single string at compile-time rather than joining separate strings 
at run-time).  See 
.


For example:
   HelpText = ("Left click: Open spam\n"
   "Shift + Left click: Cook spam\n"
   "Right click:    Crack egg\n"
   "Shift + Right click:    Fry egg\n")

The downside is having to put an explicit "\n" at the end of each line, 
but to me that's not as bad as having to align the content to the far left.


S\Possible solution to that:

HelpText = "\n".join( ["Left click: Open spam",
...   "Shift + Left click: Cook spam",
...   "Right click:Crack egg",
...   "Shift + Right click:Fry egg"
...   ]
...   )

To PEP-008 Police:
Apologies for formatting - was working from original example

In this manner, the sub-strings may be placed wherever you see fit, and 
those pesky line-endings no-longer contribute to visual clutter (but 
maybe the brackets do...)


Another philosophy is to move awkward strings, such as the examples in 
this thread, 'out' of the mainline code and into a config-file (of sorts).


The PEP-008 Police are more likely to ignore transgressions in a 
'data-file' during code-review. So, you can format the code in whatever 
fashion you like...



Text for GUIs, report print-outs, etc, tends to be at the (tender) mercy 
of (opinionated) users. By putting such into a separate file, such 
changes can be made without (as much) risk of 'breaking' the code 
itself. Ultimately, if you ever have to expand the application to 
multi-tenancy, such will become necessary.


Using a separate file, you can consider if should write such as Python 
(import module) or use something else like JSON, YAML, ...

(and may God bless all who sail in her...).

YMMV!


Getting a bit more on topic, use of backslashes in strings is a bit 
different to backslashes for line continuation anyway.  You could almost 
think of "\
(newline)" in a multiline string as being like an escape sequence 
meaning "don't actually put a newline character in the string here", in 
a similar way to "\n" meaning "put a newline character here" and "\t" 
meaning "put a tab character here".


Book title: "Don't Make Me Think"
(thoroughly recommended. Author: Steve Krug)

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: TypeError: can only concatenate str (not "int") to str

2023-02-24 Thread dn via Python-list

On 25/02/2023 09.36, Hen Hanna wrote:

  TypeError: can only concatenate str (not "int") to str

thanks for the comments,  ---   esp. 2 or 3 (?) ppl  who  directly addressed it 
or commented on it.


If you haven't already, please review the Python Software Foundation's 
Code of Conduct https://www.python.org/psf/conduct/




py   and pypy  don't tell me what the (offending)  int   is

(even tho'  it'd be easy to show me the int, or 
number)

because  a Tuple, List... may produce  a long output and they don't want to 
deal with ways of abbreviating  it   (with ... )

and because  User-defined  Class object may cause another error while printing 
it.



_
   TypeError: can only join an iterable

Here too it'd help me   if  pypy (Jeannie)  could tell me what the offending 
data object is.


Observation:
- python doesn't tell you what you want
- correspondents are not telling you what you want and/or how you want
There's a common theme developing...

Suggestion: if you want help, and at the frequency with which you've 
been posting recently, would it be better not to sound like a 'troll'?



Please understand everyone here is volunteering time, in a bid to 
provide you (and each-other) with benefit.


Does the FACT that you have failed to answer several questions from 
colleagues really entitle you to demand others only directly-address you 
(and only your questions)?


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Python 3.10 Fizzbuzz

2023-02-28 Thread dn via Python-list

On 28/02/2023 12.55, Rob Cliffe via Python-list wrote:



On 27/02/2023 21:04, Ethan Furman wrote:

On 2/27/23 12:20, rbowman wrote:

> "By using Black, you agree to cede control over minutiae of hand-
> formatting. In return, Black gives you speed, determinism, and freedom
> from pycodestyle nagging about formatting. You will save time and 
mental

> energy for more important matters."
>
> Somehow I don't think we would get along very well. I'm a little on the
> opinionated side myself.

I personally cannot stand Black.  It feels like every major choice it 
makes (and some minor ones) are exactly the opposite of the choice I 
make.


--
~Ethan~
I've never tried Black or any other code formatter, but I'm sure we 
wouldn't get on.


Does this suggest, that because Black doesn't respect other people's 
opinions and feelings, that it wouldn't meet the PSF's Code of Conduct?


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Python list insert iterators

2023-03-03 Thread dn via Python-list

On 03/03/2023 21.22, Guenther Sohler wrote:

Hi Python community,

I have a got an example list like

1,  2,  3, 4, 5, 6, 7, 8, 9, 10
 T   T

and i  eventually want to insert items in the given locations
(A shall go between 2 and 3,  B shall go between 6 and 7)

Right now i just use index numbers to define the place:

A shall insert in position 2
B shall insert in position 6

However when i insert A in position 2, the index for successful insertion
of B gets wrong
(should now be 7 instead of 6)


The danger here is using the index to have meaning beyond its function 
(a position relative to the beginning/end).




No, it's not an option to sort the indexes and start inserting from the
back.


Without explaining this criteria (and any others), suggestions can only 
be guesses!



The most elegant option is not to store indexes, but list iterators, which
attach to the list element
and would automatically move, especially if an element is inserted before.

I could not find such functionality in python lists of [ 1,2,3 ]


So, if list doesn't float-your-boat, what about moving to something else?


Does python have such functionality ?
if yes, where can i find it ?


dict - where the keys indicate relative position

linked-list (https://en.wikipedia.org/wiki/Linked_list) where each value 
is accompanied by a "pointer" which addresses the next value by-index; 
and insertion/deletion is possible by exchanging pointers.

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Which more Pythonic - self.__class__ or type(self)?

2023-03-04 Thread dn via Python-list

On 04/03/2023 20.47, Peter J. Holzer wrote:

On 2023-03-03 13:51:11 -0500, avi.e.gr...@gmail.com wrote:


...

No. Even before Python existed there was the adage "a real programmer
can write FORTRAN in any language", indicating that idiomatic usage of a
language is not governed by syntax and library alone, but there is a
cultural element: People writing code in a specific language also read
code by other people in that language, so they start imitating each
other, just like speakers of natural languages imitate each other.
Someone coming from another language will often write code which is
correct but un-idiomatic, and you can often guess which language they
come from (they are "writing FORTRAN in Python"). Also quite similar to
natural languages where you can guess the native language of an L2
speaker by their accent and phrasing.


With ph agree I do...

or do you want that in a DO-loop with a FORMAT?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Cutting slices

2023-03-05 Thread dn via Python-list

On 06/03/2023 11.59, aapost wrote:

On 3/5/23 17:43, Stefan Ram wrote:

   The following behaviour of Python strikes me as being a bit
   "irregular". A user tries to chop of sections from a string,
   but does not use "split" because the separator might become
   more complicated so that a regular expression will be required
   to find it. But for now, let's use a simple "find":
|>>> s = 'alpha.beta.gamma'
|>>> s[ 0: s.find( '.', 0 )]
|'alpha'
|>>> s[ 6: s.find( '.', 6 )]
|'beta'
|>>> s[ 11: s.find( '.', 11 )]
|'gamm'
|>>>

   . The user always inserted the position of the previous find plus
   one to start the next "find", so he uses "0", "6", and "11".
   But the "a" is missing from the final "gamma"!
   And it seems that there is no numerical value at all that
   one can use for "n" in "string[ 0: n ]" to get the whole
   string, isn't it?




I would agree with 1st part of the comment.

Just noting that string[11:], string[11:None], as well as string[11:16] 
work ... as well as string[11:324242]... lol..


To expand on the above, answering the OP's second question: the numeric 
value is len( s ).


If the repetitive process is required, try a loop like:

>>> start_index = 11   #to cure the issue-raised

>>> try:
... s[ start_index:s.index( '.', start_index ) ]
... except ValueError:
... s[ start_index:len( s ) ]
...
'gamma'


However, if the objective is to split, then use the function built for 
the purpose:


>>> s.split( "." )
['alpha', 'beta', 'gamma']

(yes, the OP says this won't work - but doesn't show why)


If life must be more complicated, but the next separator can be 
predicted, then its close-relative is partition().
NB can use both split() and partition() on the sub-strings produced by 
an earlier split() or ... ie there may be no reason to work strictly 
from left to right
- can't really help with this because the information above only shows 
multiple "." characters, and not how multiple separators might be 
interpreted.



A straight-line approach might be to use maketrans() and translate() to 
convert all the separators to a single character, eg white-space, which 
can then be split using any of the previously-mentioned methods.



If the problem is sufficiently complicated and the OP is prepared to go 
whole-hog, then PSL's tokenize library or various parser libraries may 
be worth consideration...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: test

2023-03-07 Thread dn via Python-list

On 08/03/2023 11.48, Jim Byrnes wrote:
haven't received anything from the list for quite awhile. Got no 
response when I tried to contact the administrator.


ACK

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


ANN: The long white computing cloud

2023-03-07 Thread dn via Python-list

The long white computing cloud
- hybrid meeting, ie both in-person and virtual attendance
Wed 15 March, 1800 for 1830 (NZDT) = 0530 UTC


1 Cloud and Proud - Digital Sovereignty in Aotearoa
Doug Dixon, CEO of Catalyst Cloud, Aotearoa New Zealand's cloud provider.

2 Python in the cloud
How to get-started with the admin-stuff, and build a toy-application 
live-demo.

(what could possibly go wrong!?)


NB This will be a hybrid event and RSVPs are requested: 
https://www.meetup.com/nzpug-auckland/events/291789444/



All welcome!
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Implementing a plug-in mechanism

2023-03-15 Thread dn via Python-list

On 16/03/2023 01.47, Loris Bennett wrote:

I have written a program which, as part of the non-core functionality,
contains a module to generate email.  This is currently very specific
to my organisation, so the main program contains

   import myorg.mailer

This module is specific to my organisation in that it can ask an
internal server to generate individualised salutations for a given UID
which is known within the organisation.

I want to share the code with other institutions, so I would like to

   1. replace the organisation-specific mailer with a generic one
   2. allow an organisation-specific mailer to be used instead of the
  generic one, if so desired


This may call for the plug-in pattern, ie the user will choose whether 
to plug-in the specific, or the generic, module.


In Python, we would tend to use a Dependency Injection approach (one of 
Uncle Bob's SOLID principles).


There's a rather abstract description of the plugin pattern at 
https://martinfowler.com/eaaCatalog/plugin.html


OpenClassrooms has a more practical discussion at 
https://openclassrooms.com/en/courses/6397806-design-your-software-architecture-using-industry-standard-patterns/6896171-plug-in-architecture


There is a PyPi library called pluggy (not used it). I've used informal 
approaches using an ABC as a framework/reminder (see @George's response).


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Friday finking: IDE 'macro expansions'

2023-03-16 Thread dn via Python-list
It is a long, long, time since I've thrown one of these into the 
maelstrom of our musings.

(have the nightmares receded?)


Do you make use of your IDE's expansionist tendencies, and if-so, which 
ones?



NB this is where vi/emacs enthusiasts start chuckling (polite term for 
'insane cackling'). Hence the question's limitation to IDEs, cf 'editors'!
Also: I'm talking 'PyCharm' because of the story, but others use Codium, 
Sublime Text, etc - which presumably offer equivalent features.



Was helping a friend install PyCharm. Jumped into the Settings. Isn't it 
incredible how many there are?


Idly noted that there are two short-cut or macro-expansion types of 
facilities:

- Postfix Completion, (nothing to do with email or polish notation) and
- Live Templates (again, we're not talking about jinja2)


With both, one types an abbreviated-name and the IDE will expand it into 
appropriate code. For (LiveTemplate) example, typing compli and pressing 
Tab induces PyCharm to add the following to the program[me]:


[ ! for ! in !drop-down menu! if ! ]

It offers further typo-saving through the drop-down menu which lists a 
bunch of likely (iterable) candidates from amongst previously-written 
code. The action continues after selecting from the menu, by inviting 
completion of the other ("!") placeholders, in-turn.



I haven't made use of such a tool, to-date - OK, yes, I have practised a 
high typing-speed (and accuracy). Puff, puff...


Also, at the time, I'm thinking in 'code', rather than about what tool 
might implement said ideas.



Do you make use of such expansionist-tendencies?

Do you make use of other powerful features within the IDE, or are its 
editor functionalities employed at pretty-much the NotePad level?




Web.Refs:
https://www.jetbrains.com/help/pycharm/settings-postfix-completion.html
https://www.jetbrains.com/help/pycharm/using-live-templates.html#live_templates_types
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Friday finking: IDE 'macro expansions'

2023-03-17 Thread dn via Python-list

On 18/03/2023 02.44, Thomas Passin wrote:

On 3/17/2023 9:38 AM, Simon Ward wrote:

On Fri, Mar 17, 2023 at 02:05:50PM +0100, Roel Schroeven wrote:
Even better than simply highlighting is (IMO) a thing called "Rainbow 
Braces" or "Bracket Pair Colorization" I recently learned about: both 
braces of a matching pair get the same color, while other pairs get 
other colors. I have to say I like it quite a lot. It's in VS Code 
these days; possible there are implementations or extensions for 
other editors and IDEs as well.


VS Code also supports ‘semantic highlighting’: Instead of simply 
highlighting syntax, highlight the same identifiers in the same 
colours, with the aim of helping you see them through the flow of the 
code.


Even with a simple "Find" command I don't like that behavior, let alone 
for programming.  I find that all those other marked instances make it 
harder for me to read the surrounding material.  They are good for 
moving from one instance to another, but otherwise they get in the way 
for me.



Haven't seen the coloring feature as-described. As the number of 
identifiers increased, suspect it would become gaudy or the color 
shading too subtle for my eyes.


+1 'Busy pictures' can be distracting.


That said, the syntax-highlighting can provide the occasional cue that 
something has gone-wrong. However, will I recognise it from the 
mis-coloring, or from other evidence first?



The semantic point might be easily under-estimated. A 'simple find' may 
not be helpful - a web-search for Python turns-up irrelevant information 
about snakes!


Regarding the tracing of an identifier: PyCharm has two features:
- with cursor/caret on/at a single use of an identifier, it will 
highlight other usage, elsewhere in that module's code
- (context menu) FindUsages will bring-up a two-pane window. The 
left-pane shows a tree-structure of the project, modules, etc, down to a 
listing of each code-line where the identifier is used. Highlighting one 
of those (at a time), will show the context around that particular 
line/usage. The right-pane is editable!


The great thing about these features is that they are semantically-aware 
(is that a real term?). For example, if I were (foolish enough) to name 
an identifier "the", such searches will not 'hit' the same word inside a 
comment or docstring.


Better still, the above motivation continues into a (context menu) 
Refactor facility. This, one might consider to be a semantic 
Find-Replace. Often employ when helping others to clarify their 
code/Code Review - or when I'm 'just coding' and have quickly defined an 
identifier without a lot of thought, but later (ie when come to make use 
of it) realise a better alternative and more descriptive name.


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Friday finking: IDE 'macro expansions'

2023-03-18 Thread dn via Python-list

On 19/03/2023 01.27, 2qdxy4rzwzuui...@potatochowder.com wrote:

On 2023-03-18 at 11:49:24 +,
"Weatherby,Gerard"  wrote:


For templating, I have two Python programs for starting new work. One
generates a standalone Python program with the Python shebang, a
__main__ which calls def main(), and logging and argparser
intialization. The other generates a pyproject.toml /setup.cfg
directory structure with a main.py referenced as a console
script. from setup.cfg


You don't describe the process for using those programs, but if you
"have two Python programs," then it sounds like you're *not* using the
IDE/editor for that.

(I'm not judging, I'm trying to relate your answer to dn's original
question.)


It is a good example of a facility or 'power' of an IDE - even if 
there's room for more information...



The team I'm currently assisting has decided to use Poetry.

PyCharm will create a new project, populating basic files, more-or-less 
as @George described. In the same way, if one prefers a venv (etc) 
instead of a Poetry structure, PyCharm will set things up similarly.


Accordingly, it saves a lot of time, fiddling-about creating a bunch of 
(basically) empty files and sub-dirs.


(that said, there a plenty of operations which have a blank-project 
template which can be copied-in and renamed...)



Continuing the story, let's say the project calls for a PyPi-based* 
library, eg more_itertools, or there's a team 'standard', eg pytest; 
then these can be selected from a PyCharm-provided list (no need to go 
to PyPi to download) AND that operation will also be reflected in the 
pyproject.toml file.


* cf one from the PSL

In other words, the build file has been created and 
continually-maintained, by the IDE, ready for when the project is to be 
uploaded to a library or exported to target-machines; cf the 'tradition' 
of an extra, last, and not looked-forward-to, step in the process!




For an opposing view, I'm much more likely to copy an old project (at
the command line, often with sed) and then use my editor to morph it
into a new project.  IME, unless there's an imposed process, those
templates and programs tend to experience bitrot, whereas going back to
an old program gives me the chance to keep it up to date w.r.t. what
I've learned more recently, which helps reinforce said learning.


Yes...
(guilty as charged!)

Equally, may promulgate old habits and a lower-quality (related to the 
depth of learning, back-then cf 'now').


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Standard class for time *period*?

2023-03-28 Thread dn via Python-list

1. Is there a standard class for a 'period', i.e. length of time
   specified by a start point and an end point?  The start and end
   points could obviously be datetimes and the difference a timedelta,
   but the period '2022-03-01 00:00 to 2022-03-02 00:00' would be
   different to '2023-03-01 00:00 to 2023-03-02 00:00' even if the
   *duration* of both periods is the same.


But even if I have a single epoch, January 2022 is obviously different
to January 2023, even thought the duration might be the same.  I am just
surprised that there is no standard Period class, with which I could
create objects and then be able to sort, check for identity, equality of
length, amount of overlap, etc.  I suppose people just use a
datetime.datetime pair, as I have been doing so far, and tack on just
the specific bit of functionality they need.


The request for a "standard class" has probably been answered.

Please give a use-case example to help outline the problem to be solved...

eg if the Apple-picking season starts in January and runs for some 
weeks, and the Pear-picking season starts in February (etc), then 
calculation will reveal if one team of pickers can do both jobs or if 
two teams will be needed. If a list of tasks is to be displayed/printed, 
then it would be useful to list both, but in chronological order - 
perhaps by start-date.
(this idea of possible application fails to illustrate a rationale for 
some of the functionality listed, above, but you get the idea of how to 
give us the idea...)


In a custom-class, an __eq__( self, other, ) may be defined to consider 
any single or combination of attributes of the two classes. So, 
roll-your-own may not be that difficult - although anything involving 
time-calculations is wont to open a can-of-worms...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Python file location

2023-03-29 Thread dn via Python-list

On 30/03/2023 09.47, windhorn wrote:

I have an older laptop I use for programming, particularly Python and Octave, running a 
variety of Debian Linux, and I am curious if there is a "standard" place in the 
file system to store this type of program file. OK, I know they should go in a repository 
and be managed by an IDE but this seems like way overkill for the kind of programming 
that I do, normally a single file. Any suggestions welcome, thanks.


My home-directory has a sub-dir called Projects. Larger and identifiable 
projects are put in their own sub-dir of that. There are also 'buckets' 
which contain (usually single) files such as you describe, eg 
PythonTraining, NotesInClass, and the one used when folk 'here' ask 
code-questions: "experiments".


NB "Projects" may or may not be Python-based, eg may be the name of a 
course, with sub-directories off that for each lecture or tutorial.


Python doesn't actually care where code is placed. The act of running a 
script causes Python to add the script's directory to the PYTHONPATH. 
That means that it will 'find' any files used by/from the script, 
relative to that dir. Accordingly, use a dir-structure is probably more 
about exerting some order over what would otherwise quickly become a 
confusion!


As you say, I see little point in making "experiments" into a repo. The 
life-time of any such code is that of the thread/conversation (Note to 
self: should clean-up some of the old-stuff in there).


The others are set-up under git. That to enable the use of a GitLab 
instance* as a form of off-site backup, or as a means of exchange with 
others (at the project-level).


Again, agreeing with you: if PyCharm is not running, it might not be 
worth (waiting while) firing it up just to check some 'experiment'. In 
which case, either the task can be accomplished using the Python REPL, 
or maybe a simple text-editor will be quite sufficient to copy-paste 
code from an email-message and provide a basis for the-whatever (in a 
file called "Allan.py", for example), and from which a 
suggested-solution may be posted afterwards...


YMMV!

* New Zealand Open Source Society perq of membership
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: When is logging.getLogger(__name__) needed?

2023-03-31 Thread dn via Python-list

On 01/04/2023 02.01, Loris Bennett wrote:

Hi,

In my top level program file, main.py, I have

   def main_function():

   parser = argparse.ArgumentParser(description="my prog")

   ...

   args = parser.parse_args()
   config = configparser.ConfigParser()

   if args.config_file is None:
   config_file = DEFAULT_CONFIG_FILE
   else:
   config_file = args.config_file

   config.read(config_file)

   logging.config.fileConfig(fname=config_file)
   logger = logging.getLogger(__name__)

   do_some_stuff()
   
   my_class_instance = myprog.MyClass()


   def do_some_stuff():

   logger.info("Doing stuff")

This does not work, because 'logger' is not known in the function
'do_some_stuff'.

However, if in 'my_prog/my_class.py' I have

   class MyClass:

   def __init__(self):

   logger.debug("created instance of MyClass")

this 'just works'.

I can add

   logger = logging.getLogger(__name__)

to 'do_some_stuff', but why is this necessary in this case but not in
the class?

Or should I be doing this entirely differently?


Yes: differently.

To complement @Peter's response, two items for consideration:

1 once main_function() has completed, have it return logger and other 
such values/constructs. The target-identifiers on the LHS of the 
function-call will thus be within the global scope.


2 if the purposes of main_function() are condensed-down to a few 
(English, or ..., language) phrases, the word "and" will feature, eg

- configure env according to cmdLN args,
- establish log(s),
- do_some_stuff(),  ** AND **
- instantiate MyClass.

If these (and do_some_stuff(), like MyClass' methods) were split into 
separate functions* might you find it easier to see them as separate 
sub-solutions? Each sub-solution would be able to contribute to the 
whole - the earlier ones as creating (outputting) a description, 
constraint, or basis; which becomes input to a later function/method.



* there is some debate amongst developers about whether "one function, 
one purpose" should be a rule, a convention, or tossed in the trash. YMMV!


Personal view: SOLID's "Single" principle applies: there should be only 
one reason (hanging over the head of each method/function, like the 
Sword of Damocles) for it to change - or one 'user' who could demand a 
change to that function. In other words, an updated cmdLN option 
shouldn't affect a function which establishes logging, for example.



Web.Refs:
https://people.engr.tamu.edu/choe/choe/courses/20fall/315/lectures/slide23-solid.pdf
https://www.hanselminutes.com/145/solid-principles-with-uncle-bob-robert-c-martin
https://idioms.thefreedictionary.com/sword+of+Damocles
https://en.wikipedia.org/wiki/Damocles

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Windows Gui Frontend

2023-04-02 Thread dn via Python-list




On 03/04/2023 02.45, Michael Torrie wrote:

On 4/2/23 05:09, Dietmar Schwertberger wrote:

I also did evaluate all the GUI builder from time to time between
2000 and 2016 to find one that I could recommend to colleagues,
but could not find one. Then I started contributing to wxGlade
and I can say that since a few years it's as easy again to
build GUIs as it was with VB6.

I don't want to go back to coding GUIs manually. For most use
cases it's a waste of time and often it does not result in the
best GUI as it's not so easy to try out and rearrange elements.


But any modern GUI toolkit has sizers and layout managers. If you're
manually placing elements you cannot deal with HiDPI or changing window
sizes.  Rearranging happens automatically when using sizers and layout
managers.

That said, the future of GUIs is declarative, using XAML or some other
domain-specific language like QML.  Examples of this include QtQuick
(the long-term direction Qt is heading), and the various dot Net GUI
toolkits now popular including MS' own MAUI, WPF, Avalonia.

GUI designer tools (Qt Creator, Visual Studio) can be used to assist and
help layout the skeleton, but ultimately the GUI is defined by code. And
it works very well, is adaptive, and can automatically size and
rearrange. If you want portability to mobile devices, this is where it's at.

I've tried wxGlade but never could get into it, or wxWidgets in general.
  I used to use GTK a lot and did use Glade back then, and dynamically
loaded the UI definition files at run time.  Lately used more Qt with
QtDesigner, and even extended Designer to support using some custom
widgets I made.

but the future of Qt is clearly QtQuick, so I've been learning that.
Has its warts, but in general I like the declarative paradigm.  It's a
learning curve.  Overall it's fairly powerful, flexible and portable.  I
have used the designer in Qt Creator a bit, but it's often faster and
just as intuitive to write it in QML, since you're going to be dropping
into QML frequently anyway to set properties (not unlike having to set
widget properties in Qt Designer.  So I guess it's 6s using the
graphical designer vs straight Qt.


Do the two approaches acknowledge each other and enable 'round tripping'?
ie to use the best?better tool for particular jobs (and to cope with 
later-maintenance) can one start using one approach, switch to using the 
other, and then go back to the first?


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: [Python-Dev] Small lament...

2023-04-03 Thread dn via Python-list

On 04/04/2023 12.14, Guido van Rossum wrote:

A bit late, this reached my inbox:
https://peternorvig.medium.com/new-python-operators-9f31b56ddcc7


Did you notice that Peter Norvig's factorial-operator attempts to 
replace one of the very first diamond-grade provisions of [the] FLUFL?


Disgraceful behavior! So disrespectful!

Send him to the Spanish Inquisition...


Saying that, he (Peter) lost the opportunity to promote our new 
dev.movement. As he pointed-out, tests are likely to give one a false 
sense of security with regard to the correctness of code.


Accordingly, join us in the noTDD philosophy. Like NoSQL is schema-less, 
noTDD is scheme-less (we have NO idea what we're doing).


Don't be led-astray by tests. We're all [adult-]optimists here...



On Sat, Apr 1, 2023 at 11:23 AM Skip Montanaro 
wrote:


Just wanted to throw this out there... I lament the loss of waking up on
April 1st to see a creative April Fool's Day joke on one or both of these
lists, often from our FLUFL... Maybe such frivolity still happens, just not in
the Python ecosystem? I know you can still import "this" or
"antigravity", but those are now old (both introduced before 2010). When
was the last time a clever easter egg was introduced or an April Fool's Day
joke played?

¯\_(ツ)_/¯

Skip

___
Python-Dev mailing list -- python-...@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-...@python.org/message/Q62W2Q6R6XMX57WK2CUGEENHMT3C3REF/
Code of Conduct: http://python.org/psf/codeofconduct/






--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: When is logging.getLogger(__name__) needed?

2023-04-05 Thread dn via Python-list
Thank you for carefully considering suggestions (and implications) - and 
which will 'work' for you.


Further comment below (and with apologies that, unusually for me, there 
are many personal opinions mixed-in):-



On 06/04/2023 01.06, Loris Bennett wrote:

"Loris Bennett"  writes:

dn  writes:

On 01/04/2023 02.01, Loris Bennett wrote:

Hi,
In my top level program file, main.py, I have
def main_function():
parser = argparse.ArgumentParser(description="my prog")
...
args = parser.parse_args()
config = configparser.ConfigParser()
if args.config_file is None:
config_file = DEFAULT_CONFIG_FILE
else:
config_file = args.config_file
config.read(config_file)
logging.config.fileConfig(fname=config_file)
logger = logging.getLogger(__name__)
do_some_stuff()
   my_class_instance = myprog.MyClass()
def do_some_stuff():
logger.info("Doing stuff")
This does not work, because 'logger' is not known in the function
'do_some_stuff'.
However, if in 'my_prog/my_class.py' I have
class MyClass:
def __init__(self):
logger.debug("created instance of MyClass")
this 'just works'.
I can add
logger = logging.getLogger(__name__)
to 'do_some_stuff', but why is this necessary in this case but not
in
the class?
Or should I be doing this entirely differently?


Yes: differently.

To complement @Peter's response, two items for consideration:

1 once main_function() has completed, have it return logger and other
such values/constructs. The target-identifiers on the LHS of the
function-call will thus be within the global scope.

2 if the purposes of main_function() are condensed-down to a few
(English, or ..., language) phrases, the word "and" will feature, eg
- configure env according to cmdLN args,
- establish log(s),
- do_some_stuff(),  ** AND **
- instantiate MyClass.

If these (and do_some_stuff(), like MyClass' methods) were split into
separate functions* might you find it easier to see them as separate
sub-solutions? Each sub-solution would be able to contribute to the
whole - the earlier ones as creating (outputting) a description,
constraint, or basis; which becomes input to a later function/method.


So if I want to modify the logging via the command line I might have the
following:

-

#!/usr/bin/env python3

import argparse
import logging


def get_logger(log_level):
 """Get global logger"""

 logger = logging.getLogger('example')
 logger.setLevel(log_level)
 ch = logging.StreamHandler()
 formatter = logging.Formatter('%(levelname)s - %(message)s')
 ch.setFormatter(formatter)
 logger.addHandler(ch)

 return logger


def do_stuff():
 """Do some stuff"""

#logger.info("Doing stuff!")


Looks like I just need

   logger = logging.getLogger('example)
   logger.info("Doing stuff!")



def main():
 """Main"""

 parser = argparse.ArgumentParser()
 parser.add_argument("--log-level", dest="log_level", type=int)
 args = parser.parse_args()

 print(f"log level: {args.log_level}")

 logger = get_logger(args.log_level)
 logger.debug("Logger!")
 do_stuff()


if __name__ == "__main__":
 main()

-

How can I get logging for 'do_stuff' in this case without explicitly
passing 'logger' as an argument or using 'global'?

Somehow I am failing to understand how to get 'logger' defined
sufficiently high up in the program that all references 'lower down' in
the program will be automatically resolved.


At the risk of 'heresy', IMHO the idea of main() is (almost always) 
unnecessary in Python, and largely a habit carried-over from other 
languages (need for an entry-/end-point).


NB be sure of the difference between a "script" and a "module"...


My script template-overview:

''' Script docstring. '''
- author, license, etc docs

global constants such as import-s
set environment

if __name__ == "__main__":
do_this()
do_that()
ie the business of the script


Despite its frequent use, I'm somewhat amused by the apparent 
duplication within:


if __name__ == "__main__":
main()

ie if this .py file is being executed as a script, call main() - where 
main() is the purpose of the script. Whereas if the file is an import-ed 
module, do not execute any of the contained-code.


Thus, the if-statement achieves the same separation as the main() 
function encapsulation. Also, the word main() conveys considerably less 
meaning than (say) establish_logging().



NB others may care to offer alternate advice for your consideration...


There is a good argument for main(), in that it might enable tests to be 
written which assure the integration of several tasks called by the 
script. Plus, if one excludes non-TDD test-able code, such as user 
interfaces, even 'fancy headings' and print

Re: Initialising a Config class

2023-04-11 Thread dn via Python-list

On 12/04/2023 02.29, Loris Bennett wrote:

Hi,

Having solved my problem regarding setting up 'logger' such that it is

...


My reading suggests that setting up a module with a Config class which
can be imported by any part of the program might be a reasonable approach:

...


However, in my config file I am using sections, so 'config' is a dict of
dicts.  Is there any cleverer generic way of initialising the class than

...


This seems a bit clunky, because I'll end up with something like

...


So the question is: How can I map a dict of dicts onto class attributes
in a generic way such that only code which wants to use a new
configuration parameter needs to be changed and not the Config class
itself?  Or should I be doing this differently?

Note that the values from ConfigParser are all strings, so I am fine
with the attributes being strings - I'll just convert them as needed at
the point of use (but maybe there is also a better way of handling that
within a class).


Good progress!

The first achievement has been related to the (OO) concept of 
"encapsulation" - collecting related data into one place.


The second, has been the making of this, globally-accessible within the 
application.



The balancing-act may now have become: making sub-sets of the data 
available.


Thus, describing which database server and schema/view to use is part of 
the application's environment/config, just as much as the labels, eg 
company name, used in the GUI or reporting. Such data has been collected 
together (into a single 'source of truth'), but will be used in quite 
separate and/or disparate functionality within the application.


The config file has been (sensibly) split into sections - when the code 
is dealing with the DB it does not need to be concerned with 
GUI-settings - or vice-versa.


Accordingly, and like any other class (encapsulation), having been 
collected en-masse (or 'amassed', eg cmdLN options combined with a 
JSON/YAML/.ini file's settings) the data should be delivered 
appropriately. Thus, a 'getter' method (or property) to deliver the name 
of the company (likely a string). The one for the database may deliver a 
dict or key-value pairs which can be immediately 'pasted' into some 
db-open function-call...


Such retrieval-methods will be targeted to the sub-systems of the 
application. They can perform formatting and coercion tasks, as 
necessary, eg construct full-name from two or more separate data-items, 
eg first_name and family_name, or perhaps providing floats where the 
config-collection only receives strings. (best to 'hide' all that within 
the class, than require the application to deal with the 'clunkiness'). 
Plus, they could?should provide whatever combination of data-items is 
appropriate to THAT part of the application's need for config-data or 
constraints. (etc)



Stuff as much as is possible into the config class - how to collect 
environment-data, and satisfying any/all demands for its use. Then, the 
application can be relieved of all detail ("give me what I want"), only 
asking for whatever it requires, when it requires, and in the format it 
requires - tailored and ready for immediate-use...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Dataclasses, immutability(?), and ChatGPT

2023-04-11 Thread dn via Python-list

Are dataclasses (or instances thereof) mutable or immutable?
- and in what sense?


Have been experimenting with ChatGPT. In particular: its possibilities 
as a trainer, good ideas for methods of introducing new topics, its 
capability for drawing-up demonstrations or examples, its interpretation 
of assessment questions (ie evaluating my own work, eg do they test 
desired specifics, is it possible/likely to misinterpret the question, ...)



Conversed with ChatGPT about the differences between (standard) 
custom-classes and dataclasses, and when one might prefer one over the 
other.


We(?) started discussing how dataclasses might be introduced to trainees 
currently only familiar with Python's built-ins: "...how they are 
superior to using built-in data-constructs..."


Amongst the four benefits ChatGPT listed was:
«
Immutable instances: By default, instances of dataclasses are immutable, 
which means that once created, their attributes cannot be modified. This 
can help to prevent unintended modifications to the data.

»

Huh? If we'd been discussing namedtuples over (say) dictionaries, I'd 
perhaps have accepted the reply.



The next step was to write some code to double-check my understanding 
(reproduced below). No change there.

(given that I'm perfect...cough, cough, splutter)


Thus, back to ChatGPT to seek clarification:
«
You said "Immutable instances: By default, instances of dataclasses are 
immutable, which means that once created, their attributes cannot be 
modified. This can help to prevent unintended modifications to the 
data." The attribute-values within a data-class can be changed. In what 
way are Python dataclasses immutable?

»

ChatGPT did indeed clarify that:
«
You're correct that the attribute values within a dataclass can be 
changed, even though the instance itself is considered immutable.

»

That's better. The machine is as smart as I am - or I, as smart as it - 
or something(?)



However, the supporting-explanation then appears to argue against its 
own clarification (and the assertion in the question):

«
So to clarify, when we say that instances of dataclasses are immutable, 
we mean that the attributes of an instance cannot be changed after it is 
created.


In other words, if you create an instance of a dataclass, its attributes 
cannot be modified by any external code. If you want to change the value 
of an attribute, you need to create a new instance of the dataclass with 
the updated attribute value.


... [code excised - see below]

This is because the instance is considered immutable, and its attributes 
cannot be changed directly. Instead, we need to create a new instance of 
the dataclass with the updated attribute value, like this...


Now, new_person is a new instance of the Person dataclass with the 
updated attribute values, while the original person instance remains 
unchanged.


So to summarize, while the attribute values within a dataclass can be 
changed, instances of dataclasses are considered immutable because their 
attributes cannot be modified directly once they are created. Any 
updates to the attributes require the creation of a new instance of the 
dataclass.

»

[Note]
In and amongst the above explanatory-paragraphs it gives example 
code-snippets. Those are condensed into:


>>> from dataclasses import dataclass
>>>
>>> @dataclass
... class Person:
... name: str
... age: int
...
>>> person = Person(name='Alice', age=20)
>>>
>>> person.name = 'Bob'  # raises AttributeError: can't set attribute
>>> person.age = 21  # raises AttributeError: can't set attribute

- note the erroneous comments about exceptions being raised
(they weren't/aren't)!


Here's a home-grown version illustrating all the points made during the 
investigation, by way of proof/disproof:


""" PythonTraining:dataclass.py
Prove/disprove claim made by Chat-GPT.
"""

__author__ = "dn, IT&T Consultant"
__python__ = "3.11"
__created__ = "PyCharm, 12 Apr 2023"
__copyright__ = "Copyright © 2023~"
__license__ = "MIT"

# PSL
from dataclasses import dataclass


@dataclass
class Coordinates():
"""Sample dataclass. """
x:int
y:int


if __name__ == "__main__":
print( "\nCommencing execution\n" )

coordinates = Coordinates( 1, 2, )
print( coordinates, id( coordinates ), )
coordinates.x = 3
print( coordinates, id( coordinates ), )
coordinates.z = 4
print( coordinates, id( coordinates ), )
print( coordinates.x, coordinates.y, coordinates.z, )


### output:
Commencing execution

Coordinates(x=1, y=2) 140436963150928
Coordinates(x=3, y=2) 140436963150928
Coordinates(x=3, y=2) 140436963150928
3 2 4

Terminating
###

Not only are a dataclass instance's attribute-values mutable, but 
further attributes can be dynamically-added to the object-instance!


Yes, if the code included:

coordinates = Coordinates( 5, 6, )

the new "coordinates" identifier would point to a different id() 
'address', ie a fresh immutable-instance.



The 'book of wo

Re: Pycharm IDE

2023-04-18 Thread dn via Python-list

On 19/04/2023 11.18, Kevin M. Wilson via Python-list wrote:

Greetings... Kevin here:I need help, as you have guessed!I have this line: The 
Print Statement... Why complain about a 'comma', or a ')'???def play_game():
 number = random.randint(1, LIMIT)
 print (f'"I am thinking of a number between 1 to {LIMIT}\n")Or is this a 
setting in the IDE, I need to reassign?


The code is a bit difficult to read (wrapping), but the error message 
may be an assumption (on Python's part).


Should the line be:

print( F"I am thinking...
^
no extraneous/unbalanced apostrophe here?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Pycharm IDE

2023-04-19 Thread dn via Python-list

Kevin,

As mentioned in another response, the format of these messages seems 
very confused.


Please copy-paste all of (the pertinent part of) the code, and ensure 
that the line-endings are in the correct places, tab/indentation looks 
correct, etc?
(this will allow us to copy the same code into our PyCharm software and 
see what is happening!)


There still appears to be both an apostrophe (') and quotation-marks 
("). Do you want the user to see one/both?


There was mention of this being an input prompt - hence the 
question-mark. Are you aware that this could be done as part of the 
input() function?


How about creating a string and then printing that, eg

prompt = f'"I am thinking of a number between 1 to {LIMIT}"
print( prompt )

NB because of the question asked earlier, the above code is NOT 
syntactically-correct Python!

NBB am assuming there's previous code which defines LIMIT



On 19/04/2023 17.27, Kevin M. Wilson via Python-list wrote:

Ok, I got rid of the "print (f'"I am thinking of a number between 1 to {LIMIT}\n")"print 
("I am thinking of a number between 1 to {LIMIT}\n"),
and Pycharm stopped complaining about it... WHY??
Perplexed
"When you pass through the waters, I will be with you: and when you pass through the 
rivers, they will not sweep over you. When you walk through the fire, you will not be 
burned: the flames will not set you ablaze."
Isaiah 43:2

 On Tuesday, April 18, 2023 at 11:17:52 PM MDT, Kevin M. Wilson via Python-list 
 wrote:
  
  print (f'"I am thinking of a number between 1 to {LIMIT}\n")I had the impression that the format specifier 'f' was necessary for the print function, but the double quotes are for the string printed to the user, as a prompt!The Pycharm IDE is showing that it expects a single quotation mark or ')'! No error message is displayed.

Perplexed
"When you pass through the waters, I will be with you: and when you pass through the 
rivers, they will not sweep over you. When you walk through the fire, you will not be 
burned: the flames will not set you ablaze."
Isaiah 43:2

     On Tuesday, April 18, 2023 at 06:44:37 PM MDT, aapost 
 wrote:
  
  On 4/18/23 19:18, Kevin M. Wilson wrote:

Why complain about a 'comma', or a ')'???
       print (f'"I am thinking of a number between 1 to {LIMIT}\n")


my version says it expects ' first (to close the fstring)
then on a new line below it, it mentions the comma and )
I believe that is just showing you after ' it expects you to end the
print with ) as you have
or , to add additional arguments to print


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Pycharm IDE

2023-04-19 Thread dn via Python-list

On 19/04/2023 21.13, Kevin M. Wilson wrote:
Sorry the code snippet I sent was what is written in PyCharm. LIMIT is 
defined and is not causing an error!
PyCharm is flagging the Parentheses at the end. It is not seeing the 
Parentheses as the end of the print function.


def play_game():
number= random.randint(1, LIMIT)
 print (f'"I am thinking of a number between 1 to {LIMIT}\n")

Observe... Look at the color of the parenthesis, it's green!!!
!!! = WTH



Same question!

Please explain: why is there a (single) apostrophe?

NB some email clients don't notice list communications and ReplyList - 
you may need to do that manually...


--
Regards,
=dn

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


Re: PyCharm's strict PEP and not so strict?

2023-04-19 Thread dn via Python-list

On 20/04/2023 04.25, Alan Gauld wrote:

On 19/04/2023 10:51, Kevin M. Wilson via Python-list wrote:

  I'm in a bit of a quandary, I want some strict syntax errors to be flagged,


OK, You might want to use a "linter" in that case because most
tools use the interpreter itself to flag syntax errors.



  but the use of single quotes vs double quotes!
NOT what I need from the 'checker', you dig?


Not really. What is the problem. Use of single versus double quotes
is straightforward - use one or the other and make sure they
match(opening and closing) You can nest one type inside the
other if you need literal quotes. And of course the same applies
to triple quotes except you can include newlines inside those.

What kind of problems are you experiencing with quotes?
If we have some specific examples we can give specific answers.


"stones" for bull, how do I set up the kind of "checking" I want?


That's not a phrase with which I'm familiar but my guess
is you need to install a linter tool and then, possibly
configure it to flag or hide particular error/warning types
to your personal taste. Each tool is different so you
will need to read the docs on how to configure it
(and how to plumb it into your IDE).

Personally I've never felt the need for any stricter error
checking than the interpreter provides so I can't offer
anything beyond the generic suggestion to use a linter.


+1

PyCharm enables a range of Python-linters. Some by add-in. Some by 
"External tools" 
(https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html).


Once a linter is made-available, some allow one to tune the application 
or relaxation of certain 'rules', eg whether commas in a comma-separated 
list are to be followed by a space.


Whether any enable the restriction of quotes use is another matter - 
probably for the reasons @Alan has already covered.


PyCharm auto-magically enters both an opening-quote and a closing-quote 
whenever start typing a string. The 'trick' is not to delete the close 
whilst editing.


After gaining experience, I have a convention of when to use apostrophes 
and when double-quotes. These old eyes dislike mixing both in a single 
expression - but sometimes it is the best course to follow.


YMMV!

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: PyCharm's strict PEP and not so strict?

2023-04-19 Thread dn via Python-list
mmendation: (for the good of your blood-pressure) stay away from 
"highly opinionated" alternatives, such as Black. Try the ones which 
offer options to turn-on/-off particular situations (as described earlier).




"stones" for bull, how do I set up the kind of "checking" I want?

That's not a phrase with which I'm familiar but my guess is you need to 
install a linter tool and then, possibly configure it to flag or hide 
particular error/warning types to your personal taste. Each tool is 
different so you will need to read the docs on how to configure it (and 
how to plumb it into your IDE).


Sorry, at 67 I use the idioms of many eras! "Stones", 'balls'...


Let's try to dispute another old saw - the one about "old dogs"...
Then there's "slowly, slowly, catchee..."
(but all of these are probably regarded as 'politically incorrect', and 
anything disrespectful of others transgresses the Python Code of 
Conduct, so let's park 'the attitude' right there)


@Alan is an accomplished author - even if more familiar with British 
slang, rather than Spanish 'translations'. This list is blessed by 
contributions from people from all around the globe. Accordingly, 
there'll be many who are unable to understand your/my aphorisms and 
allusions. Hence trying to stay with a more 'international English'.



"When you pass through the waters, I will be with you: and when you pass 
through the rivers, they will not sweep over you. When you walk through 
the fire, you will not be burned: the flames will not set you ablaze."

*Isaiah 43:2*


On Wednesday, April 19, 2023 at 11:39:36 AM MDT, dn via Python-list 
 wrote:



On 20/04/2023 04.25, Alan Gauld wrote:
 > On 19/04/2023 10:51, Kevin M. Wilson via Python-list wrote:
 >>   I'm in a bit of a quandary, I want some strict syntax errors to be 
flagged,

 >
 > OK, You might want to use a "linter" in that case because most
 > tools use the interpreter itself to flag syntax errors.
 >
 >
 >>  but the use of single quotes vs double quotes!
 >> NOT what I need from the 'checker', you dig?
 >
 > Not really. What is the problem. Use of single versus double quotes
 > is straightforward - use one or the other and make sure they
 > match(opening and closing) You can nest one type inside the
 > other if you need literal quotes. And of course the same applies
 > to triple quotes except you can include newlines inside those.
 >
 > What kind of problems are you experiencing with quotes?
 > If we have some specific examples we can give specific answers.
 >
 >> "stones" for bull, how do I set up the kind of "checking" I want?
 >
 > That's not a phrase with which I'm familiar but my guess
 > is you need to install a linter tool and then, possibly
 > configure it to flag or hide particular error/warning types
 > to your personal taste. Each tool is different so you
 > will need to read the docs on how to configure it
 > (and how to plumb it into your IDE).
 >
 > Personally I've never felt the need for any stricter error
 > checking than the interpreter provides so I can't offer
 > anything beyond the generic suggestion to use a linter.


+1


PyCharm enables a range of Python-linters. Some by add-in. Some by
"External tools"
(https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html).

Once a linter is made-available, some allow one to tune the application
or relaxation of certain 'rules', eg whether commas in a comma-separated
list are to be followed by a space.

Whether any enable the restriction of quotes use is another matter -
probably for the reasons @Alan has already covered.

PyCharm auto-magically enters both an opening-quote and a closing-quote
whenever start typing a string. The 'trick' is not to delete the close
whilst editing.

After gaining experience, I have a convention of when to use apostrophes
and when double-quotes. These old eyes dislike mixing both in a single
expression - but sometimes it is the best course to follow.

YMMV!

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list 
<https://mail.python.org/mailman/listinfo/python-list>



<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
  Virus-free.www.avg.com 
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>


--
Regards,
=dn

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


Re: Pycharm IDE

2023-04-19 Thread dn via Python-list

On 20/04/2023 08.59, Thomas Passin wrote:

On 4/19/2023 4:06 PM, Mark Bourne wrote:


print(f'{LIMIT})


^ I think this one should be:

print(f'{LIMIT}')

with the closing quote ;o)


Yup a typo!  Where's pylint when I need it?


but (and you designed it this way - right?) an excellent object-lesson 
for the OP


AND

great rationale for why linters are so handy!


I am bullish on F-strings, but they can stretch the typing fingers and 
strain the eyes. Remember the days when pythonista used to make 
deprecating remarks about the superiority of Python's syntax because we 
didn't have 'all those braces' (and other punctuation-characters) 
cluttering-up the code???


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Question regarding unexpected behavior in using __enter__ method

2023-04-20 Thread dn via Python-list

On 21/04/2023 10.44, Lorenzo Catoni wrote:

I am writing to seek your assistance in understanding an unexpected
behavior that I encountered while using the __enter__ method. I have
provided a code snippet below to illustrate the problem:


It is expected behavior - just not what WE might have expected!



class X:

... __enter__ = int
... __exit__ = lambda *_: None
...

with X() as x:

... pass
...

x

0


Note that what is happening is the creation of an alias for the int 
built-in function.


The docs say:
«
class int(x=0)
class int(x, base=10)

Return an integer object constructed from a number or string x, or 
return 0 if no arguments are given. If x defines __int__(), int(x) 
returns x.__int__(). If x defines __index__(), it returns x.__index__(). 
If x defines __trunc__(), it returns x.__trunc__(). For floating point 
numbers, this truncates towards zero.

...
»

(https://docs.python.org/3/library/functions.html#int)

No argument is given. int() delivers as-promised. Hence, the x == 0 
result obtained.





As you can see, the __enter__ method does not throw any exceptions and
returns the output of "int()" correctly. However, one would normally expect
the input parameter "self" to be passed to the function.

On the other hand, when I implemented a custom function in place of the
__enter__ method, I encountered the following TypeError:

```

def myint(*a, **kw):

... return int(*a, **kw)
...

class X:

... __enter__ = myint
... __exit__ = lambda *_: None
...

with X() as x:

... pass
...
Traceback (most recent call last):
   File "", line 1, in 
   File "", line 2, in myint
TypeError: int() argument must be a string, a bytes-like object or a real
number, not 'X'
```
Here, the TypeError occurred because "self" was passed as an input
parameter to "myint". Can someone explain why this unexpected behavior
occurs only in the latter case?

I tested this issue on the following Python versions, and the problem
persists on all of them:
- Python 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0] on linux
- Python 3.10.10 (main, Feb  8 2023, 14:50:01) [GCC 9.4.0] on linux
- Python 3.10.7 (tags/v3.10.7:6cc6b13, Sep  5 2022, 14:08:36) [MSC v.1933
64 bit (AMD64)] on win32

I appreciate any input or insights that you might have on this matter.



(you know this next part!)

However, if int() is fed an X-object, which in no way represents a 
numeric or numeric-able value, then it crashes. After the class 
definition, try:


int( X )

=> int 0


Right-y-ho: the evidence.

Firstly, what happens when int() is called with no argument?

print( "int", int(), )


Note that whereas int and myint are both called with no argument(s), and 
therefore int() defaults to 0, myint is attempting to use the arguments 
as part of its return-value - "pass-through".


As identified, the first argument (the a-tuple's zero-th element) is 
going to be x's self - which is NOT numeric, stored in a tuple - which 
is NOT numeric...



Thus, if we "shadow" the built-in int() with a user-function, we can see 
what is being passed-in


def int( *a, **kw, ):
print( locals(), )
print( "a", a, type( a ), id( a ), )
print( len( a ), a[ 0 ], type( a[ 0 ], ) )
print( "kw", kw, type( kw ), id( kw ), )
return 42

class X:
__enter__ = int
__exit__ = lambda *_: None

with X() as x:
pass

print( "After first CM", x, "\n\n")

del( int )


def myint(*a, **kw):
print( locals(), )
print( "a", a, type( a ), id( a ), )
print( len( a ), a[ 0 ], type( a[ 0 ], ) )
print( "kw", kw, type( kw ), id( kw ), )
return int(*a, **kw)

class Y:
__enter__ = myint
__exit__ = lambda *_: None


print( Y, type( Y ), id( Y ), )

with Y() as y:
print( y, type( y ), id( y ), )
pass

print( y )


=>
{'a': (<__main__.X object at 0x7f9b6bf13b90>,), 'kw': {}}
a (<__main__.X object at 0x7f9b6bf13b90>,)  140305733882528
1 <__main__.X object at 0x7f9b6bf13b90> 
kw {}  140305734120576
After first CM 42


  93904023389520
{'a': (<__main__.Y object at 0x7f9b6bf2c0d0>,), 'kw': {}}
a (<__main__.Y object at 0x7f9b6bf2c0d0>,)  140305507712640
1 <__main__.Y object at 0x7f9b6bf2c0d0> 
kw {}  140305507621376
Traceback (most recent call last):
  File "/home/dn/Projects/analyzer/lorenzo.py", line 53, in 
with Y() as y:
  File "/home/dn/Projects/analyzer/lorenzo.py", line 44, in myint
return int(*a, **kw)
   ^
TypeError: int() argument must be a string, a bytes-like object or a 
real number, not 'Y'



If you remover the del() and leave my play-version of int(), Python can 
make it work...


(the second half of the output)

  94557671306576
{'a': (<__main__.Y object at 0x7f950ee2c0d0>,), 'kw': {}}
a (<__main__.Y object at 0x7f950ee2c0d0>,)  140278176579200
1 <__main__.Y object at 0x7f950ee2c0d0> 
kw {}  140278176487936
{'a': (<__main__.Y object at 0x7f950ee2c0d0>,), 'kw': {}}
a (<__main__.Y object at 0x7f950ee2c0d0>,)  140278176579152
1 <__main__.Y object at 0x7f950ee2c0d0> 
k

Re: Disable 'style PEP' messages

2023-05-04 Thread dn via Python-list

On 05/05/2023 04.28, Kevin M. Wilson via Python-list wrote:

Hi... How do I set Pycharm to find only syntax errors?!!


Please review response to previous message re:configuring PyCharm's 
helpful features towards to coders and quality-coding...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Addition of a .= operator

2023-05-20 Thread dn via Python-list

On 21/05/2023 05.54, Alex Jando wrote:

I have many times had situations where I had a variable of a certain type, all 
I cared about it was one of it's methods.

For example:


import hashlib
hash = hashlib.sha256(b'word')
hash = hash.hexdigest()

import enum
class Number(enum.Enum):
 One: int = 1
 Two: int = 2
 Three: int = 3
num = Number.One
num = num.value


Now to be fair, in the two situations above, I could just access the method 
right as I declare the object, however, sometimes when passing values into 
functions, it's a lot messier to do that.

So what I'm suggesting is something like this:


import hashlib
hash = hashlib.sha256(b'word')
hash.=hexdigest()

import enum
class Number(enum.Enum):
 One: int = 1
 Two: int = 2
 Three: int = 3
num = Number.One
num.=value



A custom-class wrapper?
Even, a decorator-able function?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


OT: Addition of a .= operator

2023-05-23 Thread dn via Python-list

On 24/05/2023 10.21, Rob Cliffe via Python-list wrote:



This sort of code might be better as a single expression. For example:

user = (
 request.GET["user"]
 .decode("utf-8")
 .strip()
 .lower()
)
user = orm.user.get(name=user)


LOL.  And I thought I was the one with a (self-confessed) tendency to 
write too slick, dense, smart-alec code. 😁
Indeed, I was itching to shorten it (starting with the low-hanging 
fruit: user = user.strip().lower() ).
Seriously though: this kind of condensation can come unstuck when any of 
the steps need to be made more complicated.

...

Peter's actual code feels more Pythonic to me.  (It's even 2 lines 
shorter! 😎)


On 24/05/2023 09.03, Peter J. Holzer wrote:
> I sometimes have a chain of transformations (e.g. first decode it, then
> strip extra spaces, then normalize spelling, then look it up in a
> database and replace it with the record, ...). Technically, of course
> all these intermediate objects are different, and I could make that
> explicit by using different variable names:
>
>  user_param = request.GET["user"]
>  user_decoded = str(user_param, encoding="utf-8")
>  user_stripped = user_decoded.strip()
>  user_normalized = user_stripped.lower()
>  user_object = orm.user.get(name=user_normalized)
>
> But I find it easier to read if I just reuse the same variable name:
>
>  user = request.GET["user"]
>  user = str(user, encoding="utf-8")
>  user = user.strip()
>  user = user.lower()
>  user = orm.user.get(name=user)
>
> Each instance only has a livetime of a single line (or maybe two or
> three lines if I have to combine variables), so there's little risk of
> confusion, and reusing the variable name makes it very clear that all
> those intermediate results are gone and won't be used again.


Once again/recently/another trainee came with a question about input() 
because he expected an number (cf input() providing a string). In this 
case, and to drive-home the point, preferred training illustration is:


quantity_input = input( "How many would you like? " )
quantity = float( quantity_input )

Many others, and I dare so all those who suffer from the aforementioned 
"itch", want to condense this into a single line.


However, (continuing @Peter's theme) such confuses things when something 
goes wrong - was the error in the input() or in the float()?

- particularly for 'beginners'
- and yes, we can expand the above discussion to talk about 
error-handling, and repetition until satisfactory data is input by the 
user or (?frustration leads to) EOD...


Accordingly, I'd start by favoring @Peter's "explicit" approach. However 
(as mentioned), we end-up with a bunch of names (storage-space) which 
are essentially unused - and many lint-er types will deplore such 
single-use [like it's s-u plastic].


Thus, advice becomes somewhat the opposite(!) of function parameter 
handling - there, I'm happy with one or two positional-parameters, but 
by three-or-more, this over-taxed brain starts begging/itching for 
named-parameters instead.


Now, the "easier" approach appeals. Indeed, if something goes wrong (per 
input()/float(), above), at least one has the assistance of a 
line-number (where error was noted). Further, using the PyCharm 
Debugger/pdb makes locating the design-error/coder's mistaken 
assumption, a snap.


A debatable-point is how much we should consider more junior-level 
programmers. IMHO more common functions such as strip() and lower() can 
be combined without much loss of readability or comprehension (apart 
from 'function-chaining' adding complication). Whereas, the other three 
lines are more likely to challenge - and/or become a source of concern 
if mods are requested...


However, some disagreement - which comes back to why the "_input" suffix 
(above) acts as an aide-memoire: When "user" is first used (hah!), it is 
the result of an http request. It is then transmogrified, until at the 
end where it is a query-result/object. Yes, however contrived and 
deliberately drawn-out the example, there is still a difference between 
the value which the code first produces (request/input) and that which 
eventually settles-out (orm/float).


Accordingly (perhaps), "user_request" or "user_requested" and "user" or 
"user_record" (according to the way 'that' ORM operates). Perhaps more 
psychology rather than coding?


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: OT: Addition of a .= operator

2023-05-23 Thread dn via Python-list

On 24/05/2023 12.27, Chris Angelico wrote:

On Wed, 24 May 2023 at 10:12, dn via Python-list  wrote:

However, (continuing @Peter's theme) such confuses things when something
goes wrong - was the error in the input() or in the float()?
- particularly for 'beginners'
- and yes, we can expand the above discussion to talk about
error-handling, and repetition until satisfactory data is input by the
user or (?frustration leads to) EOD...


A fair consideration! Fortunately, Python has you covered.

$ cat asin.py
import math

print(
 math.asin(
 float(
 input("Enter a small number: ")
 )
 )
)
$ python3 asin.py
Enter a small number: 1
1.5707963267948966
$ python3 asin.py
Enter a small number: 4
Traceback (most recent call last):
   File "/home/rosuav/tmp/asin.py", line 4, in 
 math.asin(
ValueError: math domain error
$ python3 asin.py
Enter a small number: spam
Traceback (most recent call last):
   File "/home/rosuav/tmp/asin.py", line 5, in 
 float(
ValueError: could not convert string to float: 'spam'

Note that the line numbers correctly show the true cause of the
problem, despite both of them being ValueErrors. So if you have to
debug this sort of thing, make sure the key parts are on separate
lines (even if they're all one expression, as in this example), and
then the tracebacks should tell you what you need to know.



Yes, an excellent example to show newcomers to make use of 'the 
information *provided*' - take a deep breath and read through it all, 
picking-out the important information...



However, returning to "condense this into a single line", the 
frequently-seen coding is (in my experience, at least):


quantity = float( input( "How many would you like? " ) )

which would not produce the helpful distinction between 
line-numbers/function-calls which the above (better-formatted) code does!



Summarising (albeit IMHO):

- if relatively trivial/likely to be well-known: collect the calls into 
a chain, eg


user = user.strip().lower()

- otherwise use separate lines in order to benefit from the stack-trace

- (still saying) use separate assignments, rather than chaining more 
complex/lesser-known combinations


- ensure that the 'final' identifier is meaningful (and perhaps the 
first, and/or even an 'intermediate' if pertinent or kept for re-use later)


- perhaps re-use a single identifier-name as a temp-variable, if can 
reasonably 'get away with it'

(and not confuse simple minds, like yours-truly)


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: complaint

2023-05-30 Thread dn via Python-list

Hi Daniel,

On 31/05/2023 02.40, Daniel Ifechukwude Dibie wrote:

i tried to uninstall the python 3.11.3 program from my machine so that i
can re-install it is showing successful but it is ligerning on the program
and features


Is that word "lingering". If so, do you mean that Python did not 
uninstall properly - or do you mean that the reinstalled version is slow 
to operate?


Not understanding the question, I threw it into ChatGPT:-


User
i tried to uninstall the python 3.11.3 program from my machine so that i
can re-install it is showing successful but it is ligerning on the 
program and features


ChatGPT
If you are experiencing issues uninstalling Python 3.11.3 from your 
machine, here are a few steps you can try to resolve the problem:


Restart your computer: Sometimes, a simple restart can help resolve 
issues related to the uninstallation process.


Use an uninstaller tool: You can try using a third-party 
uninstaller tool to remove Python 3.11.3 from your system. These tools 
are designed to thoroughly remove programs, including any leftover files 
or registry entries. Some popular uninstaller tools include Revo 
Uninstaller, IObit Uninstaller, and Geek Uninstaller.


Manual uninstallation: If the above steps don't work, you can try 
manually uninstalling Python 3.11.3. Here's how you can do it:
Open the "Programs and Features" or "Apps & Features" section 
in your computer's control panel.

Locate Python 3.11.3 in the list of installed programs.
Click on Python 3.11.3 and select the "Uninstall" or "Remove" 
option.
Follow the on-screen instructions to complete the 
uninstallation process.
After the uninstallation is complete, you may also want to 
delete any remaining Python-related folders or files from your system. 
These are typically located in the "C:\Python3.11" directory.


Please note that manually deleting files from your system can be risky 
if you're not familiar with the process. Be cautious and ensure that 
you're deleting the correct files associated with Python 3.11.3.


Once you have successfully uninstalled Python 3.11.3, you can proceed 
with reinstalling it on your machine. Make sure to download the 
installer from the official Python website (https://www.python.org) and 
follow the installation instructions provided.



User
i tried to uninstall the python 3.11.3 program from my machine so that i
can re-install it is showing successful but it is slow to load the 
program and features


ChatGPT

If the uninstallation process appears to be successful, but you are 
experiencing slow loading of the "Programs and Features" section in the 
control panel, there might be a few possible reasons for this issue. 
Here are some steps you can take to troubleshoot the problem:


Wait for a while: Sometimes, the uninstallation process might take 
some time to complete all the necessary tasks, especially if it's a 
large program like Python. It's possible that the program is still 
finalizing its uninstallation in the background. Give it some time and 
see if the "Programs and Features" section starts responding normally 
after a few minutes.


Restart your computer: Restarting your computer can help resolve 
any lingering processes or system issues that may be causing the slow 
loading of the "Programs and Features" section. After restarting, try 
accessing the control panel again and see if the problem persists.


Check for other processes or services: It's possible that other 
processes or services running on your computer are causing a slowdown. 
Close any unnecessary applications and check if there are any 
resource-intensive processes running in the background. You can open the 
Task Manager (Ctrl+Shift+Esc) to check for any unusually high CPU or 
memory usage.


Check for system errors: Run a scan for system errors using the 
built-in Windows System File Checker (SFC) tool. Open a Command Prompt 
as an administrator and run the command: sfc /scannow. This will scan 
your system for any corrupted or missing system files and attempt to 
repair them.


Reinstall Python: If the issue persists, you can try reinstalling 
Python 3.11.3 again after performing the above steps. Make sure to 
follow the official installation instructions and download the installer 
from the official Python website (https://www.python.org).


If none of the above steps resolve the slow loading issue, there might 
be underlying system issues causing the problem. You may consider 
seeking further assistance from a technical expert or your system 
administrator to diagnose and resolve the issue.



NB I do not use MS-Windows (which is an assumption - not stated in OP), 
and thus cannot vouch for the veracity of this advice, nor for its 
accuracy - caveat emptor!


Hope one of those sets of ideas will help...
- will be interested to hear how you get on...
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Best practice for database connection

2023-05-31 Thread dn via Python-list

On 01/06/2023 06.45, Thomas Passin wrote:

On 5/31/2023 2:10 PM, Jason Friedman wrote:

I'm trying to reconcile two best practices which seem to conflict.

1) Use a _with_ clause when connecting to a database so the connection is
closed in case of premature exit.

class_name = 'oracle.jdbc.OracleDriver'
url = f"jdbc:oracle:thin:@//{host_name}:{port_number}/{database_name}"
with jdbc.connect(class_name, url, [user_name, password],
jdbc_jar_file.as_posix()) as connection:
 logger.info(f"Connected.")

2) Use self-made functions to streamline code. For example, there are
several places I need to know if the database object is a particular 
type,

so I create a function like this:

foobar_set = set()
...
def is_foobar(connection: jdbc.Connection, name: str) -> bool:
 """
 :param connection: connection object
 :param name: owner.object
 :return: True if this object is of type foobar
 """
 global foobar_set
 if not foobar_set:
 query = f"""select stuff from stuff"""
 cursor = connection.cursor()
 cursor.execute(query)
 for owner, object_name in cursor.fetchall():
 foobar_set.add(f"{owner}.{object_name}")
 cursor.close()
 return name.upper() in foobar_set


But that requires that I call is_foobar() with a connection object.

Essentially I'd like a function that leverages the one connection I 
create

at the beginning using a with clause.


If you need to have a connection object that persists outside of the 
with block, then


1. you can just not use a "with" block:

connection = jdbc.connect(class_name, url, [user_name, password],
    jdbc_jar_file.as_posix())

You will want to close the connection yourself when you are done with it.

2. do all the subsequent work within the "with" block.


As with many such questions, the answer is "it depends". Sadly that's no 
help!



Please consider: is the database critical to this application? In other 
words, if the script is unable to proceed without access, eg RDBMS is 
down or credentials are not accepted, then must the logic simply stop?


Most of mine fit into that category. Accordingly, script-execution 
starts with setting the environment, eg gathering credentials; followed 
by establishing a connection to the RDBMS. An operational RDBMS is part 
of the environment! Now (wait for many of our colleagues to hurriedly 
suck in their breath) we can see that the connection is a global-value - 
something which resides in a base "frame" of the Python stack, and is 
accordingly available (R-O) 'everywhere'.


NB when I say "connection", it is part of a wider RDBMS-interface object.

If you wish to use a Context Manager, then its only content may be a 
call to main() - or preferably a function which better describes what 
the application will do. (per @Thomas' contribution)


PS I don't like using the global keyword/command, but prefer to pass the 
connection as a parameter. A matter of style? A "contract": 
no-connection, no-query? YMMV...



Another approach might be to enact the Dependency Inversion Principle 
(one of 'Uncle Bob' Martin's SOLID Principles. In this case, proceed 
with the application, and when it comes time to issue a query against 
the database, ask the question: "does a connection exist?". In the 
negative case, then call a routine which establishes the connector, 
passes that to the query-routine, and proceeds.


Assuming multiple query-routines, the problem with this is that it takes 
some sleight-of-hand to create a shared connection. Alternately, maybe 
the application is prepared to assume the 'cost' of creating multiple 
connections (over time) because the RDBMS-interactions are few-and-far 
between, or only a small part of the total.



I don't use one, but others enthuse about ORMs, eg SQLAlchemy. This 
suits those who combine RDBMS and OOP, and has its own persistence 
methodology.


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Enum + new in 3.11

2023-06-15 Thread dn via Python-list
Have you figured-out a use for the @enum.member and @enum.nonmember 
decorators (new in Python 3.11)?



"What's New" says:
Added the member() and nonmember() decorators, to ensure the decorated 
object is/is not converted to an enum member.


The PSL docs say:
@enum.member
A decorator for use in enums: its target will become a member.

also:
enum members have names and values (the name of Color.RED is RED, the 
value of Color.BLUE is 3, etc.)


Whereas the "Utilities and Decorators" section is slightly confusing 
because class decorators are mixed with others, so one has to read 
more-carefully.



"Curiosity killed the cat" and other cautionary tales/tails...

Have added the following decorated staticmethod to a basic enum. It is 
indeed recognised as a member of the enum, but its value is the 
method-object. To gain the value the method-object represents 
(property-like behavior) one has to call the method/enum-value as a 
function:-



from enum import Enum, member


class MenuOptions( Enum ):
""" Legal menu-choices. """
N = "NewGame"
L = "LoadGame"
# ...

@member
@staticmethod
def extra_member()->str:
return "QuitGame"


def print_demo( enum_chosen:MenuOptions )->None:
""" Illustrative printing. """
print( "Name:", enum_chosen, enum_chosen.name )
if isinstance( enum_chosen, MenuOptions ):
print( "Value:", enum_chosen.value )


print( MenuOptions.__members__ )
# {'N': , 'L': , 
'extra_member': MenuOptions.extra_member at 0x7f0802128860>)>>}


print_demo( MenuOptions[ "L" ] )
# Name: MenuOptions.L L
# Value: LoadGame

print_demo( MenuOptions.extra_member )
# Name: MenuOptions.extra_member extra_member
# Value: 0x7f0802128860>)>


print( MenuOptions.extra_member.value() )
# QuitGame


Therefore, like an @property decorator applied to a method in a 
custom-class, it could be used to only evaluate some 'expensive' 
computation if/when it is needed. Similarly, it could use the other 
values within the enum in order to present some 'combination'.


Weirdly (given that enums are considered immutable) I imagine that if 
the 'extra_member' were to call some external function with varying 
output, the value could be considered mutable when it is eventually called.


Other?better ideas...

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Enum + new in 3.11

2023-06-16 Thread dn via Python-list

On 16/06/2023 23.47, Thomas Passin via Python-list wrote:

On 6/16/2023 1:40 AM, dn via Python-list wrote:
Have you figured-out a use for the @enum.member and @enum.nonmember 
decorators (new in Python 3.11)?




mypy is having trouble with 3.11 enums:

"There are 83 open Enum mypy issues at the the time of this writing.

Getting the Enum datatype to work with mypy is becoming impossible as I 
find myself having to use cast() in at least every other line."


(see https://gi


thub.com/python/mypy/issues/12841)


There have also been other changes to enum  in 3.11 - here is a useful 
rundown:


https://www.andy-pearce.com/blog/posts/2023/Jan/whats-new-in-python-311-new-and-improved-modules/#enum

I had no idea



Sorry to hear about mypy. PyCharm has its own mechanism - if there's 
something like mypy underneath, I don't know [which].


TBH I haven't noticed any such difficulties, BUT haven't tried using 
more than a defined sub-class of Enum - and using such as a class. Thus:


class MenuOptions( Enum ):
""" Legal menu-choices. """
N = "NewGame"
L = "LoadGame"



if __name__ == "__main__":
n:MenuOptions = MenuOptions.N
print( n, type( n ) )
# MenuOptions.N 

works correctly, but strikes me as pedantry.
(any (mypy) problematic code you'd like me to try (in PyCharm) as a 
comparison? Perhaps off-list - could summarise any pertinent discoveries 
later...)



I tried messing with the enum-members, eg N:str; but realised that 
although this worked/was passed silently, the name of a member is not 
actually a string anyway. So, backed that out.



Had noted the first web.ref but deemed it unimportant (to me - as 
above). The second I had not found, and enjoyed reading (many thanks!).


«I’ll be honest, I struggled to think of concrete cases where this would 
be useful, since I don’t tend to pile additional functionality into my 
enumerations — they’re almost always just bare classes which are members 
of another class or module which provides the related functionality. But 
I think it’s good to broaden your horizons...»


The last being the same view as led me to this point, and the first, the 
motivation for this post! As said, I tend to only use enums in a fairly 
mechanistic fashion.


However, I have been playing-around with his "additional functionality". 
For example, adding the idea of a default-value if an enquiry attempts 
to use a 'key' which is not present (which seems 'natural', but equally 
goes against (my understanding of) the ethos of an enum). Next, (see 
earlier comment about having to invoke the @member-target as a function) 
was the idea that if one is using an enum as a collection of the correct 
choices/responses in a menu (per code snippet), making the member.value 
into a function* attempts to reproduce the idiom of using a dict[ionary] 
to simulate a case/select construct - which combines the idea of an 
API's constants with making a decision as to which functionality should 
be invoked.


* function here (cf "method") because unlikely to locate such 
functionality within the enum. However, am also experimenting with 
classes (cue OOP-mumblings, eg "polymorphism", "inversion", ...)


All the fun of the fair!

BTW when I reach the point of making comparisons, I expect the enum will 
be 'cheaper' in storage; but that the dict-construct will be 'faster' - 
pure speculation(!) Repeating: curious cats, etc...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Should NoneType be iterable?

2023-06-19 Thread dn via Python-list

On 20/06/2023 06.12, Neal Becker via Python-list wrote:

On Mon, Jun 19, 2023 at 12:42 PM Chris Angelico via Python-list <
python-list@python.org> wrote:


On Tue, 20 Jun 2023 at 02:37, Peter Bona via Python-list
 wrote:


Hi

I am wondering if there has been any discussion why NoneType  is not

iterable My feeling is that it should be.

Sometimes I am using API calls which return None.
If there is a return value (which is iterable) I am using a for loop to

iterate.


Now I am getting 'TypeError: 'NoneType' object is not iterable'.

(Examples are taken from here

https://rollbar.com/blog/python-typeerror-nonetype-object-is-not-iterable/
)

Example 1:
mylist = None
for x in mylist:
 print(x)  <== will raise TypeError: 'NoneType' object is not iterable
Solution: extra If statement
if mylist is not None:
 for x in mylist:
 print(x)


I think Python should handle this case gracefully: if a code would

iterate over None: it should not run any step. but proceed the next
statement.


Has this been discussed or proposed?



Try this instead:

for x in mylist or ():

Now a None list will skip iteration entirely, allowing you to get the
effect you want :)

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


I prefer iteration of None to be an error, as in my usage it usually
indicates a mistake that I'd want to catch


Agreed!

A better approach is that the API return (perhaps a tuple of) both 
"status" and "return_value", rather than overloading the latter.


That said, apparently the OP use-case is for when there is no interest 
in status/catch, eg where a 'nothing' answer is THE answer.


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Python Issue

2023-06-21 Thread dn via Python-list

On 22/06/2023 03.28, Pickle Pork via Python-list wrote:

Python is unable to open. Exit Code: 1


This is not good.

Please give some useful information:
- from where did you download Python?
- which operating system?
- how do you "open" Python?
etc.

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: my excel file is not updated to add new data

2023-06-26 Thread dn via Python-list

Marc,

Apologies for writing in English (the language of this Discussion List). 
I have attempted to keep the code in French...


Thanks for this question. If it's OK with you, I would like to use it as 
an example-problem (and 'solution') challenge for some future Python 
Users' Group meeting (suitably translated, etc)...



On 27/06/2023 05.46, small marcc via Python-list wrote:


This code creates the path to the Excel file where the data will be written. It 
checks if the file already exists, and if so, reads the existing data into a 
DataFrame. Otherwise, it creates a new empty DataFrame. Then it concatenates 
the existing data with the new data and writes the result to the Excel file. 
Finally, it displays a message that the backup was successful and closes the 
information window.

I do not understand why it does not work, the new data is not displayed in 
excel when I am in python tkinter, my data in python must be displayed in excel.
I use the following code to write data to an excel file using pandas:

please help meHowever, when I run this code, the new data is not showing in the 
excel file. I don't understand why this isn't working. Can you help me solve 
this problem?


Is this a Python problem, or a problem with the way the solution has 
been coded?


There are several steps in the solution-description. It is troubling (to 
both of us) that you are unable to locate the source of the error. Why? 
Because it is not noticed until the final stage "new data is not displayed"!


NB am ignoring that the line defining "df" and everything thereafter, 
appears to be incorrectly indented - when viewed in my email-client. 
That said, the sequence of events seems muddled.



Please review the code. Compare it to the verbal/English-language 
description of the solution. Can each sentence in the solution be easily 
identified in the code?


Words like "and", "otherwise", "then", and "finally" indicate that there 
are multiple steps in the process. Let's split the separate sentences 
and phrases:


- creates the path to the Excel file where the data will be written
- checks if the file already exists
[establish DataFrame]
  - if so, reads the existing data into a DataFrame
  - Otherwise, it creates a new empty DataFrame
- concatenates the existing data with the new data
- writes the result to the Excel file
- displays a message that the backup was successful
- closes the information window.

NB addition of a task-label summarising the two DataFrame alternative 
situations.



Now, we can outline the Python code by writing a bunch of function 
definitions:


def create_data_path():
def check_for_file():
def establish_data_frame():
  def read_existing_data():
  def create_new_data_frame():
def accept_new_data():
def save_to_file():
def report():
def terminate():

NB my IDE would grumble and complain if I did this 'for real'. In a 'new 
code' situation, you may like to add a pass-statement inside each, and 
vertical-spacing to make the distracting-complaints 'go away'. 
Alternately and assuming the function-name doesn't say it all, add a 
docstring (you're going to add one anyway, right?) and expand upon the 
function-name with some explanation of what the function will do. In 
this situation, you could add the existing code.


NBB the two sub-tasks have been indented here for continuity of flow. 
They may/may not be nested within establish_data_frame() when you detail 
the content of each function - not important to this outline.


NBBB I've quickly drafted function-names for the sake of this 
discussion. I find it easier to name things when it is time to use them 
(in this case, call the function). Fortunately, a competent IDE will 
facilitate the refactoring of names ("symbols"). Yes, doing it that way 
costs (me) little extra effort - but it saves straining my brain 
up-front. That said, investing time in 'designing' a good name, will 
also tend to clarify and sharpen one's thinking. So, apparently I follow 
both paths... YMMV!



Now that the solution has been outlined, one can consider what output 
you expect from each function, what input it will require to produce 
that, and the transformation in-between. For example:


def create_data_path( nom_fichier ):
* copy existing code into here
return chemin_fichier_excel

(pausing at the one function, for now...)

[for non-French speakers:
nom_fichier = file_name
chemin_fichier_excel = data path including file-name
]


How has this design-process improved things?

1 clearer thinking: we have a simple and more straightforward idea of 
what should happen
2 "separation of concerns": each function does one job (and should do it 
well!)
3 testability: we can now ensure that the (each) function performs 
correctly (in isolation)
4 the problem of locating the source of an error is simplified (in fact, 
the "testability" advantage may solve this problem - or in a new-design 
situation, avoid it*)



Testing the function is carried-out by calling the function

Hybrid meeting ANN: Using properties and descriptors

2023-07-11 Thread dn via Python-list
This month's meeting (Wed 19 July, 1800 for 1830 NZST = 0600/0630 UTC) 
will cover more-advanced OOP Python skills. You will be most-welcome to 
join us...



"Using properties and descriptors" will look at a series of 
code-examples exploring problems and how these constructs offer 
solutions. The presentations are in lecture-style. If there's time (or 
for later study), some coding workshops will be suggested.


Prerequisite knowledge or experience for "Properties":
Object-Oriented Programming (in Python), coding custom-classes, using 
available decorators, some experience in data organisation/design, 
PEP-008 and coding styles, and reading type-hints.


Prerequisite knowledge or experience for "Descriptors":
"Properties" topic in this series, coding custom-classes with 'magic 
methods', implementing inheritance and composition, design-experience in 
data organisation, Object-Oriented Design, decent understanding of OOP 
philosophy.


Hints: A lab-/log-book will be useful for taking notes. A headset will 
ease asking questions, answering questions, and discussion. Python IDE 
ready for coding.


Two choices for attendance: online or in-person (Parnell, Auckland). 
Please RSVP to book-in and receive access information:-


- Remote attendance RSVP: 
https://www.meetup.com/nzpug-auckland/events/njdjssyfckbzb/

- In-person RSVP to https://www.meetup.com/nzpug-auckland/events/294745326/

You are cordially invited to join us!
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


isinstance()

2023-08-02 Thread dn via Python-list
Can you please explain why a multi-part second-argument must be a tuple 
and not any other form of collection-type?



The signature is: isinstance(object, classinfo)
leading to "classinfo" of:

1/ a single class/type, eg int
2/ a tuple of same, eg ( int, str, )
3/ a union type, eg int | str (v3.10+)

A question was asked about this at last night's PUG-meeting. The person 
was using the union option, but from Python v3.8. Sorting that out, he 
replaced the union with a list. No-go! Before correcting to a tuple...


Why does the second argument need to be a tuple, given that any series 
of non-keyword arguments is a tuple; and that such a tuple will still 
need to be delimited by parentheses. In other words, other forms of 
delimiter/collection, eg list and set; being a series of 
elements/members would seem no different.


Yes, the underlying C operation appears to only accept a single argument 
(am not C-soned, mea culpa!).


There is some discussion about hashability, but isn't it coincidental 
rather than constructive? (again, maybe I've not understood...)


Enquiring minds want to know...


Web.Refs:
https://docs.python.org/3/library/functions.html?highlight=isinstance#isinstance
https://docs.python.org/3/c-api/object.html?highlight=isinstance#c.PyObject_IsInstance
https://docs.python.org/3/reference/datamodel.html?highlight=isinstance

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: How to find the full class name for a frame

2023-08-03 Thread dn via Python-list

On 04/08/2023 15.34, Jason Friedman via Python-list wrote:

import inspect

def my_example(arg1, arg2):
print(inspect.stack()[0][3])
my_frame = inspect.currentframe()
args,_,_,values = inspect.getargvalues(my_frame)
args_rendered = [f"{x}: {values[x]}" for x in args]
print(args_rendered)

my_example("a", 1)


The above "works" in the sense it prints what I want, namely the method
name (my_example) and the arguments it was called with.


The above didn't 'work' - please copy-paste and ensure that the 
email-client is respecting indentation.




My question is: let's say I wanted to add a type hint for my_frame.

my_frame: some_class_name = inspect.currentframe()

What would I put for some_class_name?
"frame" (without quotations) is not recognized,
Nor is inspect.frame.


We know Python code is executed in an execution frame. 
(https://docs.python.org/3/reference/executionmodel.html?highlight=frame)


We are told "Frame objects Frame objects represent execution frames." 
(https://docs.python.org/3/reference/datamodel.html?highlight=frame). 
The word "represent" conflicts with the idea of "are".


'Under the hood' inspect calls sys._current_frames() 
(https://docs.python.org/3/library/sys.html?highlight=frame). That code is:


def _getframe(*args, **kwargs): # real signature unknown
"""
Return a frame object from the call stack.

If optional integer depth is given, return the frame object that many
calls below the top of the stack.  If that is deeper than the call
stack, ValueError is raised.  The default for depth is zero, returning
the frame at the top of the call stack.

This function should be used for internal and specialized purposes
only.
"""
pass

Which rather suggests that if the sys library doesn't know the 
signature, then neither typing nor we mere-mortals are going to do so, 
either.



Theory: the concept of a frame does not really exist at the Python-level 
(remember "represents"). Frames (must) exist at the C-level 
(https://docs.python.org/3/c-api/frame.html?highlight=frame#c.PyFrameObject) 
of the virtual-machine - where typing is not a 'thing'.



It's an interesting question. Perhaps a better mind than mine can give a 
better answer?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: isinstance()

2023-08-04 Thread dn via Python-list

On 03/08/2023 11.38, Jon Ribbens via Python-list wrote:

On 2023-08-02, dn  wrote:

Can you please explain why a multi-part second-argument must be a tuple
and not any other form of collection-type?


The following comment may hold a clue:

 if (PyTuple_Check(cls)) {
 /* Not a general sequence -- that opens up the road to
recursion and stack overflow. */

https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684

Plus an almost total lack of demand for change I should think.


Thanks for the reference!


Am not proposing a change (have learned 'the rule' and accepted 
life-as-it-is), but was curious about the restriction: why not any 
(reasonable sequence)?



Such pondering continues in my subversive mind, given such thoughts as:

- "we're all adults here"
(eg frequent justification when arguing about Python not having "private 
attributes" per-se).

So, if we introduce a complexity, on our own heads be it!
(hardly likely given that all we are likely to attempt is the 
application of a simple and short 'list' of [un]acceptable types).
NB understood that the quoted-code is applied in many and other 'scalar 
or tuple' situations.


- Python happily enables recursion, which "opens up the road to 
recursion and stack overflow.".

So, why install a 'nanny' to save us from ourselves here?
Again: seems on-the-surface that such 'lists' (at the code-line level) 
will be mono-dimensional 99.9% of the time.



NB having said that, the underlying mechanism *is* multi-dimensional: 
"direct, indirect, or virtual) subclass thereof" 
(https://docs.python.org/3/library/functions.html#isinstance)


Further: the 'rules' say: "classinfo is a tuple of type objects (or 
recursively, other such tuples)". Thus, can write:


>>> target_object = ...
>>> inner_tuple = float, complex
>>> inner_tuple
(, )
>>> isinstance( target_object, ( str, inner_tuple, int, ), )
False

I can't say I've ever used such construction in-the-wild - either 
defining and then using an "inner_tuple", or even nesting. YMMV!



Any thoughts?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: isinstance()

2023-08-04 Thread dn via Python-list

On 05/08/2023 11.18, Chris Angelico via Python-list wrote:

On Sat, 5 Aug 2023 at 09:08, dn via Python-list  wrote:


On 03/08/2023 11.38, Jon Ribbens via Python-list wrote:

On 2023-08-02, dn  wrote:

Can you please explain why a multi-part second-argument must be a tuple
and not any other form of collection-type?


The following comment may hold a clue:

  if (PyTuple_Check(cls)) {
  /* Not a general sequence -- that opens up the road to
 recursion and stack overflow. */

https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684

Plus an almost total lack of demand for change I should think.


Thanks for the reference!


Am not proposing a change (have learned 'the rule' and accepted
life-as-it-is), but was curious about the restriction: why not any
(reasonable sequence)?


There are quite a few places where the only option is a tuple.


"spam".startswith(["sp", "h"])

Traceback (most recent call last):
   File "", line 1, in 
TypeError: startswith first arg must be str or a tuple of str, not list

try: 1/0

... except [ValueError, IndexError]: pass
...
Traceback (most recent call last):
   File "", line 1, in 
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
   File "", line 2, in 
TypeError: catching classes that do not inherit from BaseException is
not allowed

It simplifies a lot of checks. Either it's a tuple or it's a single
thing. A *lot* of values are iterable, but only tuples are tuples.

As the C comment notes, this also means you don't have to worry about
recursion; otherwise, even core language features like exception
handling would have to iterate over a thing while ensuring that they
don't get stuck in self-referential objects. (Incidentally, it seems
that exception handling doesn't bother with recursion *at all*, and
won't catch "(a, (b, c))" - but even if recursion is handled, it can't
go infinite, short of some serious messing around in ctypes or the C
API.)

Yes. Thanks Chris!

The idea that such 'lists' be immutable (even, hashable), and therefore 
a tuple, makes a certain amount of sense, and @Cameron mentioned 
'frugality'.



My limitation is thinking only at the Python level (which as @Jon 
pointed-out, is only part of the story).


Faced with a situation where an argument may be a scalar-value or an 
iterable, I'll presume the latter, eg throw it straight into a for-loop. 
If that fails (because the argument is a scalar), use try-except to 
re-route the logic. Alternately, in an OOP situation, utilise 
polymorphism so that the 'scalar' and 'iterable' instances both include 
the appropriate method[name]. Accordingly, as long as the argument is an 
iterable (includes an __iter__() method), the actual type/class is 
more-or-less irrelevant.



However, as observed earlier - and with these additions, having learned 
the 'rule', ie use a tuple; the brain is still pondering, but have 
shrugged-shoulders and carried-on regardless...


--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Where is the error?

2023-08-06 Thread dn via Python-list

On 07/08/2023 08.41, Peter J. Holzer via Python-list wrote:

Mostly, error messages got a lot better in Python 3.10, but this one had
me scratching my head for a few minutes.

...



The error message is now a lot better, of course, but the fact that it
points at the expression *before* the error completely threw me. The
underlined expression is clearly not missing a comma, nor is there an
error before that. My real program was a bit longer of course, so I
checked the lines before that to see if I forgot to close any
parentheses. Took me some time to notice the missing comma *after* the
underlined expression.

Is this "clairvoyant" behaviour a side-effect of the new parser or was
that a deliberate decision?


Found myself chuckling at this - not to be unkind, but because can 
easily imagine such confusion on my own part.


The issue of unhelpful error messages or information aimed at a similar 
but different context, has been the story of our lives. Advice to 
trainees has always been to cast-about looking for the error - rather 
than taking the line-number as a precise location. Have made a note to 
avoid advising folk to work 'backwards'!


Meantime (back at the ranch?), haven't experienced this. Using an IDE 
means all such stuff is reported, as one types, through highlights and 
squiggly lines (which should(?) be considered and cleared - before 
pressing the GO-button).


In this case, the PyCharm* editor adds red-squiggles where the commas 
should have been. Hovering the cursor over a squiggle, the IDE reports 
"',' expected"! Its PythonConsole behaves similarly (without offering a 
'hover'). Plus, even after the closing brace, it continues to assume a 
multi-line compound-statement (and thus won't execute, per expected REPL 
behavior).



Way-back (grey-beard time!) when we submitted card-decks of code to be 
compiled over-night, one idea to avoid expensive, trivial errors/eras; 
was that spelling-checkers should be built-in to compilers, eg to 
auto-magically correct typos, eg


AFF 1 TO TOTAL

instead of:

ADD 1 TO TOTAL

These days, we can look at code from two or more years ago, 'produced' 
by ChatGPT (et al), aka "The Stochastic Parrot". There is some thought 
that artificial 'intelligence' will one-day be able to do the coding for 
us/predict what is required/act as a crystal ball...


Speaking of which, and just because I could, here's what Chat-GPT had to 
say when I asked "what's wrong with ...":


«The issue in the given Python code is that you're missing commas 
between the key-value pairs in the dictionary. Commas are required to 
separate different key-value pairs within a dictionary. Here's the 
corrected version of the code:

...
»

Question: If a Chat-AI is built into the IDE (I stripped such out from 
mine), does it take-over error reporting and diagnosis (and offer the 
option of replacing with its 'corrected version'?) - rather than 
requiring an extra copy-paste step, per above?

(and need for my assumption of where the error is located)


Hope you've exerted copyright over the "clairvoyant" description!


* JetBrains kindly sponsor our PUG with a monthly door-prize.
--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Mtg ANN: Using computer vision AI to help protect the worlds rarest dolphin

2023-08-08 Thread dn via Python-list

Wed 16 Aug 2023, 1800~20:30 NZST (0600~0830 UTC, late-Tue in US)
Details and RSVP at https://www.meetup.com/nzpug-auckland/events/295091858/


Teaching a computer to see. How computer vision is helping to protect 
the world’s rarest dolphin and how you can train your own model.


Tane van der Boon will talk about the MAUI63 project, and then lead us 
through how to train and utilise a custom computer vision object 
detector. Essentially allowing our software to be able to see.


MAUI63 was given its name because when the venture began, there were 
only 63 Māui dolphins left in existence. Using drone technology and AI 
to collect and process visual data, the founders took action to collect 
data to help save the world’s rarest dolphin from extinction and 
influence future marine conservation efforts.


The MAUI63 team uses a customised drone to find and track the movement 
of dolphins, and enables individual dolphins to be identified through 
their fin markings. The information collected can then be used to inform 
better data driven decisions on how best to protect them.


Later, Tane will lead us through a smaller task to build our own image 
recognizer. (more details in due course...)



The Auckland Branch of the New Zealand Python Users' Group meet twice 
monthly. You're very welcome to attend online or in-person (as 
available). Meeting location-details or URL will be sent to those who RSVP.


We are a healthy mix of Python users. Students, academics, hobbyists, 
industry professionals, and many completely new to Python.


The "room" opens at 1800 (local time) with an opportunity to network 
with colleagues. Everything should be wrapped up by 2030.


We are always keen to hear suggestions for meeting-topics, and to meet 
with folk who'd like to present or lead - eg a brief lightning talk, a 
practical coaching-session, a full lecture... Help is available if 
you've never done such a thing before!


We follow the NZPUG Code of Conduct (https://python.nz/code-of-conduct) 
to create an inclusive and friendly environment.


We express thanks to, and encourage you to investigate, our sponsors: 
Catalyst Cloud, New Zealand Open Source Society, JetBrains, and IceHouse 
Ventures.


--
Regards =dn

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Planning a Python / PyData conference

2023-08-08 Thread dn via Python-list

Hi Wilber,


On 09/08/2023 14.28, Wilber H via Python-list wrote:

Hi,

I would like to plan a Python / PyData conference in the country of the
Dominican Republic, and would like your feedback on how to best plan
for the conference.


Recommend making your request of the folks who organise EuroPython 
and/or PyConUS - and then same for smaller gatherings.


(would suggest to ours, but those folk are already over-loaded to be 
ready in a few weeks' time)


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Imports and dot-notation

2023-08-09 Thread dn via Python-list

On 09/08/2023 22.30, Oliver Schinagl via Python-list wrote:
...> Looking at a python projects code and repository layout, we see the

following directory structure.

/project/core
/project/components/module1
...
/project/components/moduleN
/projects/util

...> Some modules import other modules, and I see (at the very least) two

(kind of three?) different ways of doing so.

`from project.components.module1 import function1, function2 as func, 
CONST1, CONST2 as CONST`


or maybe even (which has as an advantage that it becomes clear which 
namespace something belongs to


`from project.components.module1 import function1, function2 as 
module1_function2, CONST1, CONST2 as MODULE1_CONST2`


but then it really just becomes personal preference, as the number of 
characters saved on typing is almost negative (due to having a more 
complex import).


but also the dot notation being used

`from project.components import module1`

where obviously the functions are invoked as `module1.function1` etc


Firstly, the path followed will depend upon the starting position!

Keep reading and you should come across a reference to 'hobgoblin of 
little minds'.


What should we be concentrating on/about? If 'naming' is a great (?the 
greatest) challenge of programming, surely remembering the names of 
classes, methods, functions, modules, etc; follows...
(and by implication, as you've illustrated, perhaps where they 
come-from), ie code is read more often than it is written, so think 
about comprehension rather than typing!



If one (one's team!) frequently uses a module, then a jargon may 
develop. For example:


import numpy as np
...
a = np.arange(6)

In which case, those au-fait with the jargon know that the "np." prefix 
tells them where "arange()" can be found - conversely, that if the IDE 
doesn't alert, that np/numpy must be (first) import-ed.


However, there is a cognitive-load to 'translate' "np" into "numpy". Not 
much, but then over-load is not a single thought but the combination of 
'everything'.


The second option (OP) is very (laboriously) clear in mapping the source 
of each function or constant. By way of comparison then, the code may 
now appear cluttered, because there's so much text to read. There would 
be less if an abbreviation were used.


The dev.tool in-use may also influence this decision. If hovering-over 
an identifier reveals source-information, what value the extra code? 
Intelligent completion also reduces relevance of 'number of characters 
saved on typing'.


Accordingly, give frequently-used functions/modules the abbreviation 
treatment -but only if YOU feel it right. Otherwise, use a longer-form 
to improve readability/comprehension.


THE answer will thus vary by library/package/module, by application, and 
by coder (jargon works best if 'all' use it/understand same).


Side note: Using "...import identifier, ..." does not save storage-space 
over "import module" (the whole module is imported regardless, IIRC), 
however it does form an "interface" and thus recommend leaning into the 
"Interface Segregation Principle", or as our InfoSec brethren would say 
'the principle of least privilege'. Accordingly, prefer "from ... import 
... as ...".


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Context manager for database connection

2023-08-23 Thread dn via Python-list

On 24/08/2023 03.41, Jason Friedman via Python-list wrote:

I want to be able to write code like this:

with Database() as mydb:
conn = mydb.get_connection()
cursor = conn.get_cursor()
cursor.execute("update table1 set x = 1 where y = 2")
cursor.close()
cursor = conn.get_cursor()
cursor.execute("update table2 set a = 1 where b = 2")
cursor.close()

I'd like for both statements to succeed and commit, or if either fails to
stop and for all to rollback.

Is what I have below correct?


import jaydebeapi as jdbc
class Database:
 database_connection = None

 def __init__(self, auto_commit: bool = False):
 self.database_connection = jdbc.connect(...)
 self.database_connection.jconn.setAutoCommit(auto_commit)

 def __enter__(self) -> jdbc.Connection:
 return self

 def __exit__(self, exception_type: Optional[Type[BaseException]],
  exception_value: Optional[BaseException],
  traceback: Optional[types.TracebackType]) -> bool:
 if exception_type:
 self.database_connection.rollback()
 else:
 self.database_connection.commit()
 self.database_connection.close()

 def get_connection(self) -> jdbc.Connection:
 return self.database_connection



Looking good!


Assuming this is the only DB-interaction, a context-manager seems 
appropriate. If the real use-case calls for more interactions, the cost 
of establishing and breaking DB-connections becomes a consideration. 
Alternately, the 'length'?'life' of the context-manager *might* 
complicate things.


Intriguing that given such a start, the code doesn't feature a 
context-manager for a query.



That two cursors are established is also a 'cost'. Could both queries 
utilise the same cursor?
(in which case, could consider adding to __init__() or __enter__(), and 
close in __exit__() )



Because the context-manager has been implemented as a class, there is no 
reason why one can't add more methods to that class (it doesn't need to 
be limited to the functional __enter__() and __exit__() methods!


Indeed there is already get_connection(). Why not also a query( self, 
sql-code ) method?



These might reduce the mainline-code to something like:

if __name__ == "__main__":
with Database() as mydb:
mydb.query( "update table1 set x = 1 where y = 2" )
mydb.query( "update table2 set a = 1 where b = 2" )
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Context manager for database connection

2023-08-23 Thread dn via Python-list

On 24/08/2023 06.11, dn via Python-list wrote:

On 24/08/2023 03.41, Jason Friedman via Python-list wrote:

with Database() as mydb:
conn = mydb.get_connection()
cursor = conn.get_cursor()
cursor.execute("update table1 set x = 1 where y = 2")
cursor.close()
cursor = conn.get_cursor()
cursor.execute("update table2 set a = 1 where b = 2")
cursor.close()


import jaydebeapi as jdbc
class Database:
 database_connection = None

 def __init__(self, auto_commit: bool = False):
 self.database_connection = jdbc.connect(...)
 self.database_connection.jconn.setAutoCommit(auto_commit)

 def __enter__(self) -> jdbc.Connection:
 return self

 def __exit__(self, exception_type: Optional[Type[BaseException]],
  exception_value: Optional[BaseException],
  traceback: Optional[types.TracebackType]) -> bool:
 if exception_type:
 self.database_connection.rollback()
 else:
 self.database_connection.commit()
 self.database_connection.close()

 def get_connection(self) -> jdbc.Connection:
 return self.database_connection


Using a context-manager is a good idea: it ensures clean-up with/without 
an exception occurring. Accordingly, I (and may I presume, most) like 
the idea when working with life-cycle type resources, eg I/O. Absolutely 
nothing wrong with the idea!



However, the scope of a c-m is the with-block. If there are a number of 
'nested operations' to be performed (which could conceivably involve 
other c-ms, loops, or similar code-structures) the code could become 
harder to read and the length of the scope unwieldy.


An ease of management tactic is being able to see the start and end of a 
construct on the same page/screen. Such would 'limit' the length of a 
c-m's  scope.


Perhaps drawing an inappropriate parallel, but like a try-except block, 
there seems virtue in keeping a c-m's scope short, eg releasing 
resources such as a file opened for output, and some basic DBMS-es which 
don't offer multi-access.



Accordingly, why I stopped using a c-m for database work. NB YMMV!

There were two other reasons:
1 multiple databases
2 principles (and my shining virtue (?) )


1 came across a (statistics) situation where the client was using two 
DBMS-es. They'd used one for some time, but then preferred another. For 
their own reasons, they didn't migrate old data to the new DBMS. Thus, 
when performing certain analyses, the data-collection part of the script 
might have to utilise different DB 'sources'. In at least one case, 
comparing data through time, the routine needed to access both DBMS-es.

(oh what a tangled web we weave...)

2 another situation where the script may or may not actually have needed 
to access the DB. Odd? In which case, the 'expense' of the 'entry' and 
'exit' phases would never be rewarded.


Thus, 'inspired' to realise that had (long) been contravening SOLID's 
DSP advice?rule (Dependency Inversion Principle).



Accordingly, these days adopt something like the following (explaining 
it 'backwards' to aid comprehension in case you (gentle reader) have not 
come-across such thinking before - remember that word, "inversion"!)


- in the mainline, prior to processing, instantiate a database object

database = Database( credentials )

- assume the mainline calls a function which is the substance of the script:

def just_do_it( database_instance, other_args, ):
while "there's work to be done":
database.query( query, data, etc, )
# could be SELECT or UPDATE in and amongst the 'work'

- a basic outline of query() might be:

def query( self, sql, data, etc, ):
cursor = self.get_cursor()
cursor.execute( sql, data, ) # according to DB/connector, etc
# return query results

- a query can't happen without a "cursor", so either use an existing 
cursor, or create a fresh one:


def get_cursor( self ):
if not self._cursor:
connection = self.get_connection()
self._cursor = connection.cursor()
return self._cursor

NB assuming the DBMS has restrictions on cursors, I may have multiple 
connections with one cursor each, but in some situations it may be 
applicable to run multiple cursors through a single connection.


- a cursor can't exist without a "connection", so either ... :

def get_connection( self ):
if not self._connection:
self._connection = # connect to the DB
return self._connection

- to instantiate a DB-object in the first place, the class definition:

class Database:
def __init__(self):
self._connection = None
self._cursor = None

- and the one part of the exposition that's not 'backwards&#x

Co-op Group: Django web framework

2023-08-28 Thread dn via Python-list

Are you interested in learning Django?

Would like to improve your Django knowledge and skills?

Have you been picking-up Django piecemeal, and need to consolidate and 
clarify?


Do you know some Django and would like to acquire mentoring and coaching 
skills?



If so, please join us to form a Learning Django Co-op.
RSVP at https://www.meetup.com/nzpug-auckland/events/295727130/

--
Regards =dn
--
https://mail.python.org/mailman/listinfo/python-list


ANN: Wed 20 Sep: Terminal-based user interfaces (TUIs) with ease using Textual

2023-09-07 Thread dn via Python-list

Rodrigo's back! Fresh from his successes at EuroPython...

You are invited to join the next virtual NZPUG Auckland Branch meeting 
(Wed 20 Sep, 1830~2030 local, ie 0630~0830 UTC)


Learn how to build powerful terminal-based user interfaces (TUIs) with 
ease using Textual - an open-source Python framework.


Through this tutorial, you'll learn how to use features like Textual's 
built-in widgets, reactive attributes, and message-passing system, to 
start developing a simple TODO app that runs directly in your terminal.



About Rodrigo Girão Serrão:

Rodrigo has presented to NZPUG Auckland Branch previously. He speaks 
frequently at various PyCons (Python Conferences) and other gatherings.


As well as Python, he has been playing with APL, C++, and more.

Combining programming and maths, he describes himself as a mathemagician.

Rodrigo has always been fascinated by problem solving and that is why he 
picked up programming – so that he could solve more problems.


He also loves sharing knowledge, and that is why he spends so much time 
writing articles in his blog, writing on Twitter, and giving workshops 
and courses.


During the week, Rodrigo can be found banging his head against the wall 
while trying to solve a Textual bug, as he works on Textual full-time.



To RSVP (to receive the meeting-URL) and for more detail: 
https://www.meetup.com/nzpug-auckland/events/295433884/



The Auckland branch of the New Zealand Python Users Group meets twice 
monthly. You're very welcome to attend online or in-person (as 
available). Meeting location-details or URL will be sent to those who RSVP.


We are a healthy mix of Python users. Students, academics, hobbyists, 
industry professionals, and many completely new to Python.


The 'room' opens at 1815 (local time) with an opportunity to network 
with colleagues. Formal start is 1830. Aiming to finish by 2030.


We are always keen to hear suggestions for meeting-topics, and to meet 
with folk who'd like to present or lead - eg a brief lightning talk, a 
practical coaching-session, a full lecture... Help is available if 
you've never done such a thing before!


We follow the NZPUG Code of Conduct to create an inclusive and friendly 
environment.


We express thanks to, and encourage you to investigate our sponsors: 
Catalyst Cloud, New Zealand Open Source Society, JetBrains, and IceHouse 
Ventures.



--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Python Launcher Pops Up When Py-based App Is Running (Mac)

2023-09-18 Thread dn via Python-list

On 17/09/2023 13.20, James Greenham via Python-list wrote:

Hello,

On the face of it, the Python-Mac mailing list is largely inactive so I'm 
posting here since it looks like this one is livelier.



What happens when doGrab() is called from the REPL, after being 'fed' 
data you expect is valid? (per a unit-test)


What code-level debugging has been exercised?

Have you tried running the code in a debugger, in order to step into the 
(assumed) doGrab error?



Sadly, this code is so old as to have grown whiskers.
- are all the called-modules, eg webkit and the OpSys; still offering 
the appropriate interfaces, and continuing to behave in the expected 
fashion?

(anything relevant in those Release Notes?)
- in theory, Python 2 will still run. However, a reasonable proportion 
of today's Python-coders are unlikely to have ever used it.

(Sunsetting Python 2 https://www.python.org/doc/sunset-python-2/)
- were this code to be written using today's libraries, it is unlikely 
to look anything like this

(which may also be contributing to the dearth of replies)

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: path to python in venv

2023-09-27 Thread dn via Python-list


On 28/09/2023 09.32, Jon Ribbens via Python-list wrote:

On 2023-09-27, Larry Martell  wrote:

On Wed, Sep 27, 2023 at 12:42 PM Jon Ribbens via Python-list
 wrote:

On 2023-09-27, Larry Martell  wrote:

I was under the impression that in a venv the python used would be in
the venv's bin dir. But in my venvs I see this in the bin dirs:

lrwxrwxrwx 1 larrymartell larrymartell7 Sep 27 11:21 python -> python3
lrwxrwxrwx 1 larrymartell larrymartell   16 Sep 27 11:21 python3 ->
/usr/bin/python3

...

Not sure what this really means, nor how to get python to be in my venv.


WHy do you want python to be "in your venv"?


Isn't that the entire point of a venv? To have a completely self
contained env? So if someone messes with the system python it will not
break code running in the venv.


The main point of the venv is to isolate the installed packages,
rather than Python itself. I'm a bit surprised your symlinks are
as shown above though - mine link from python to python3.11 to
/usr/bin/python3.11, so it wouldn't change the version of python
used even if I installed a different system python version.



"venv — Creation of virtual environments" 
(https://docs.python.org/3/library/venv.html) starts by saying:


«The venv module supports creating lightweight “virtual environments”, 
each with their own independent set of Python packages installed in 
their site directories.»


but later expands this with: «Used to contain a specific Python 
interpreter...» even though the primary use-case treats the system 
interpreter as the "base" Python/environment.


Time for some reading and proving appropriate combinations of options?


Over the years there have been various proposals to enable multiple 
versions of Python to exist concurrently on a single machine, notably 
Python2 + Python3 - but am failing to recall any official docs on 
Python3.n + Python3.m; eg "PEP 554 – Multiple Interpreters in the 
Stdlib" (https://peps.python.org/pep-0554/).


That said there's plenty of articles on-line (which may/not feature 
venv*) such as "Multiple Python interpreters" 
(https://developer.fedoraproject.org/tech/languages/python/multiple-pythons.html)


* although the OP didn't mention an OpSys, one poster did mention 
Fedora-Linux...



NB some of this info may be dated - it is some time since conducted this 
investigation (and decided not to use venv - apologies!)


Am currently using PyCharm (courtesy of recent teams' conventions) and 
it eases both problems (which interpreter, and which 
development-environment/activation steps) but in automating 'the boring 
stuff' it will be interesting to see if in-future, I notice when the 
project is based upon an older system!
FYI 
https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-reloading-interpreter-paths.html
(I'd be surprised if the other major tool-sets don't offer something 
similar)


Disclaimer: JetBrains sponsor our local PUG-meetings with a door-prize.

--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-09-30 Thread dn via Python-list

On 01/10/2023 08.00, Karsten Hilbert via Python-list wrote:

A type annotation isn't supposed to change what code does,
or so I thought:

#
class Borg:
_instances:dict = {}

def __new__(cls, *args, **kargs):
# look up subclass instance cache
if Borg._instances.get(cls) is None:
Borg._instances[cls] = object.__new__(cls)
return Borg._instances[cls]


class WorkingSingleton(Borg):

def __init__(self):
print(self.__class__.__name__, ':')
try:
self.already_initialized
print('already initialized')
return

except AttributeError:
print('initializing')

self.already_initialized = True
self.special_value = 42


class FailingSingleton(Borg):

def __init__(self):
print(self.__class__.__name__, ':')
try:
self.already_initialized:bool
print('already initialized')
return

except AttributeError:
print('initializing')

self.already_initialized = True
self.special_value = 42

s = WorkingSingleton()
print(s.special_value)

s = FailingSingleton()
print(s.special_value)

#

Notice how Working* and Failing differ in the type annotation
of self.already_initialized only.

Output:

WorkingSingleton :
initializing
42

FailingSingleton :
already initialized <== 
Huh ?
Traceback (most recent call last):
  File 
"/home/ncq/Projekte/gm/git/gnumed/gnumed/client/testing/test-singleton.py", line 48, 
in 
print(s.special_value)
  ^^^
AttributeError: 'FailingSingleton' object has no attribute 
'special_value'


Where's the error in my thinking (or code) ?


What is your thinking?
Specifically, what is the purpose of testing self.already_initialized?

Isn't it generally regarded as 'best practice' to declare (and define a 
value for) all attributes in __init__()? (or equivalent) In which case, 
it will (presumably) be defined as False; and the try-except reworded to 
an if-else.


Alternately, how about using hasattr()? eg

if hasattr( self.already_initialized, 'attribute_name' ):
  # attribute is defined, etc


As the code current stands, the:

try:
self.already_initialized

line is flagged by the assorted linters, etc, in my PyCharm as:

Statement seems to have no effect.
Unresolved attribute reference 'already_initialized' for class 
'WorkingSingleton'.


but:

self.already_initialized:bool

passes without comment (see @Mats' response).


Question: is it a legal expression (without the typing)?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-09-30 Thread dn via Python-list

On 01/10/2023 11.25, Karsten Hilbert via Python-list wrote:

Am Sun, Oct 01, 2023 at 09:04:05AM +1300 schrieb dn via Python-list:


class WorkingSingleton(Borg):

def __init__(self):
print(self.__class__.__name__, ':')
try:
self.already_initialized
print('already initialized')
return

except AttributeError:
print('initializing')

self.already_initialized = True
self.special_value = 42



Where's the error in my thinking (or code) ?


What is your thinking?
Specifically, what is the purpose of testing self.already_initialized?


Apologies, my tending to use the "Socratic Method" with trainees (and 
avoiding any concept of personal-fault with others), means it can be 
difficult to tell if (personal*) introspection is being invited, or if I 
don't know the answer (and want to).


* personal cf Python code introspection (hah!)



The purpose is to check whether the singleton class has been
... initialized :-)

The line

self.already_initialized = True

is misleading as to the fact that it doesn't matter at all
what self.already_initialized is set to, as long as is
exists for the next time around.


Isn't it generally regarded as 'best practice' to declare (and define a value 
for) all
attributes in __init__()? (or equivalent) In which case, it will (presumably) 
be defined
as False; and the try-except reworded to an if-else.


I fail to see how that can differentiate between first-call
and subsequent call.


+1



Alternately, how about using hasattr()? eg

if hasattr( self.already_initialized, 'attribute_name' ):


That does work. I am using that idiom in other children of
Borg. But that's besides the point. I was wondering why it
does not work the same way with and without the type
annotation.


Annotations are for describing the attribute. In Python we don't have 
different instructions for declaring an object and defining it, eg


INTEGER COUNTER
COUNTER = 0

Thus, Python conflates both into the latter, ie

counter = 0
or
counter:int = 0

(both have the same effect in the Python Interpreter, the latter aims to 
improve documentation/reading/code-checking)


Typing defines (or rather labels) the object's type. Accordingly, occurs 
when the object is on the LHS (Left-hand Side) of an expression (which 
includes function-argument lists).


In this 'test for existence': in the case of WorkingSingleton(), the 
code-line is effectively only a RHS - see 'illegal' (below).


However, the annotation caused the code-line to be re-interpreted as 
some sort of LHS in FailingSingleton().
- as explained (@Mats) is understood as a 'typing expression' rather 
than 'Python code'.


Apologies: fear this a rather clumsy analysis - will welcome improvement...



 try:
 self.already_initialized

line is flagged by the assorted linters, etc, in my PyCharm as:

Statement seems to have no effect.


Well, the linter simply cannot see the purpose, which is
test-of-existence.




Question: is it a legal expression (without the typing)?

It borders on the illegal, I suppose, as the self-
introspection capabilities of the language are being
leveraged to achieve a legal purpose.



...and so we're addressing the important question: the try-test is for 
existence, cf for some value.


This can also be achieved by using the attribute in a legal expression, eg:

self.already_initialized == True


When introspecting code, if type-checkers cannot determine the purpose, 
is there likely to be a 'surprise factor' when a human reads it?

(that's Socratic! I already hold an opinion: right or wrong)


Might this remove the confusion (ref: @Mats):

self.already_initialized:bool == True

(not Socratic, don't know, haven't tested)




Which seems akin constructs for generating compatibility
between versions.


versions of ?



It seems the answer is being pointed to in Matts response.

It just mightily surprised me.


Me too!


I am slightly confused (OK, OK!) and probably because I don't have a 
good handle on "Borg" beyond knowing it is a Star Wars?Trek reference 
(apologies to the reader sucking-in his/her breath at such an utterance!).


What is the intent: a class where each instance is aware of every other 
instance - yet the word "Singleton" implies there's only one (cf a dict 
full of ...)?



Second move (also, slightly) off-topic:
I'm broadly in-favor of typing; additionally noting that trainees find 
it helpful whilst developing their code-reading skills. However, am not 
particularly zealous in my own code, particularly if the type-checker 
starts 'getting picky' with some co

Re: type annotation vs working code

2023-10-03 Thread dn via Python-list

On 02/10/2023 00.57, Karsten Hilbert via Python-list wrote:

Sorry for having conflated the core of the matter with all
the Borg shenanigans, that's where I found the problem in my
real code, so there :-)


The first question when dealing with the Singleton Pattern is what to do 
when more than one instantiation is attempted:


- silently return the first instance
- raise an exception


The 'problem' interpreting the original code was that the 'Borg 
Pattern', is not limited in number, but is where some class-attribute 
list (or dict) is used to enable all instances to be aware of each of 
the others (IIRC).


Is choosing names as important as selecting/implementing smart algorithms?



Consider this:

#
class Surprise:
def __init__(self, with_type_annotation=False):
if with_type_annotation:
try:
self.does_not_exist:bool
print('does_not_exist does exist')
except AttributeError:
print('does_not_exist does not exist')
return

try:
self.does_not_exist
print('does_not_exist does exist')
except AttributeError:
print('does_not_exist does not exist')

Surprise(with_type_annotation = False)
Surprise(with_type_annotation = True)
#

Is this how it is supposed to be ?


Wasn't this answered earlier? (@Mats)

That self.does_not_exist:bool isn't interpreted by Python to mean the 
same as self.does_not_exist.




...and so we're addressing the important question: the try-test is for 
existence, cf for
some value.

This can also be achieved by using the attribute in a legal expression, eg:

...

Might this remove the confusion (ref: @Mats):

 self.already_initialized:bool == True


Not for me as that would _create_ already_initialized on the
instance. It would not allow me to test for it.


Which seems akin constructs for generating compatibility
between versions.


versions of ?


Of the language. Sometimes one tests for existence of a given
class in a module and defines said class oneself if it does
not exist. But that's leading astray.


What is the intent: a class where each instance is aware of every other 
instance - yet
the word "Singleton" implies there's only one (cf a dict full of ...)?


The latter.


and so, returning to the matter of 'readability':

- the name "Borg" de-railed comprehension

- _instances:dict = {} implied the tracking of more than one

- should the class have been called either;

class SomethingSingleton():

or a Singleton() class defined, which is then sub-classed, ie

class Something( Singleton ):

in order to better communicate the coder's intent to the reader?

- from there, plenty of 'templates' exist for Singletons, so why do 
something quite different/alien to the reader?

(thus concurring with @Richard: "tricky" subverts 'readability')

- is it better to use a technique which 'we' will recognise, or to ask 
'us' to comprehend something 'new'?
(unless the 'new' is taking-advantage of a recent extension to the 
language, eg switch; to justify 'trail-blazing' a 
new/improved/replacement 'best practice')


- part of the 'tricky' seems to be an attempt to assess using an 
instance-attribute, rather than a class-attribute. If the :bool (or 
whichever) typing-annotation is added to a class-attribute (eg 
_instance), will the problem arise?


- does the sequence

_instance = False
...
if not cls._instance:
ie the explicit version
if cls._instance == False:

measure 'existence' or a value?

- does the sequence

_instance = None
...
if not cls._instance:
ie the explicit version:
if cls._instance is None:

measure 'existence' or identity?
(indeed, are they more-or-less the same concept?)

- do the *attr() functions test for 'existence'?

(that said, most of the code-examples I spotted, in reading-up on this, 
use either None or False - et tu Brute!)



Speaking of reading-up:

- am wondering where PEP 661 - Sentinel Values is 'going'?

- this article (https://python-patterns.guide/gang-of-four/singleton/) 
mentions that the original GoF Singleton Pattern preceded Python 
(particularly Python 3 classes). Also, that Python doesn't have 
complications present in C++. It further discusses "several drawbacks", 
which also champion 'readability' over 'trick' or 'sophistication'. I 
think you'll enjoy it!


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-10-04 Thread dn via Python-list

On 04/10/2023 19.41, Chris Angelico via Python-list wrote:

On Wed, 4 Oct 2023 at 15:27, dn via Python-list  wrote:

- should the class have been called either;

  class SomethingSingleton():

or a Singleton() class defined, which is then sub-classed, ie

  class Something( Singleton ):

in order to better communicate the coder's intent to the reader?


TBH, I don't think it's right to have a Singleton class which is
subclassed by a bunch of different singletons. They aren't really
subclasses of the same class. I could imagine Singleton being a
metaclass, perhaps, but otherwise, they're not really similar to each
other.


I'm with you on this - should have made Singleton() an ABC.

Yes, would only be a skeleton around which concrete singleton classes 
could be built.


Like you, I v.rarely use them - but which means that the ABC is useful 
because it would save me from having to remember the curly-bits 
all-over-again...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Where I do ask for a new feature

2023-10-20 Thread dn via Python-list

On 21/10/2023 01.32, Thomas Passin via Python-list wrote:

On 10/19/2023 11:16 PM, Bongo Ferno via Python-list wrote:
On Thursday, October 19, 2023 at 11:26:52 PM UTC-3, avi.e...@gmail.com 
wrote:


There are many ways to make transient variables that disappear at 
some time
and do we need yet another? Yes, you can create one of those ways but 
what

is the big deal with deleting a variable when no longer used?


Assigning a variable to something can be anything else than a temporal 
alias.
A with statement makes clear that the alias is an alias and is local, 
and it automatically clears the variable after the block code is used.


Python clutters the variable space with vars that are needed only on 
certain places, and an alias doesn't has a scope.
Convenient alias are short names, and short names are limited in 
quantity. If the space is cluttered with short alias, it opens risks 
for wrong utilization.


Its like writing a "for i" in a list comprehension and having to worry 
if "i" was already used in another place..


If a name is temporarily needed in a certain place and in a certain 
scope then reusing the name shouldn't be a problem.


Agree. Surely, the only time we use a name like "i" is in a throw-away 
context?


Under many circumstances Python will let us use "_" in place of a 
named-identifier - which enables both us and Python to remember its 
short-lived value/local-only use.


Using an alias MERELY for the convenience of a shorter-name suggests two 
things: 1 lack of a competent editor/IDE, 2 lack of imagination in 
choosing names (perhaps one of THE skills of programming!)


Yes, there are other languages which enforce a limited-scope on 
data-items created within or as part of a code-structure - and it IS a 
handy feature! On the other hand, Python's apposite stance can be useful 
too, eg trivial toy-example:


# list_of_stuff = ...

for n, element in list_of_stuff:
if element == target:
break

# now element == target, so "element" is probably not that useful
# but "n" is the index of the target-element, which may be
# (there are other ways to accomplish same)


Please take a look at the ideas behind "Modular Programming". This 
encourages the breaking-up of monolithic code and its "cluttered" global 
namespace, into potentially-independent code-units. The outlined-problem 
is solved by the independent scope of those code-units (in Python: 
modules, classes, functions, and "if __name__ == "__main__":".
(to say nothing of the coder's virtues of "re-use", the "Single 
Responsibility Principle", "do one thing, and do it well", Law of 
Demeter, ...)


Personal comment: my habit is to break specs into many classes and 
functions - sometimes more-so than others might prefer. Cannot recall 
when last had that hard-to-locate bug of unwittingly re-using a name/alias.

(apologies: not a boast - a recommendation for going modular)

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: return type same as class gives NameError.

2023-10-22 Thread dn via Python-list

On 23/10/2023 04.50, Antoon Pardon via Python-list wrote:

I have the following small module:

=-=-=-=-=-=-=-=-=-=-=-= 8< =-=-=-=-=-=-=-=-=-=-=-=-=

from typing import NamedTuple, TypeAlias, Union
from collections.abc import Sequence

PNT: TypeAlias = tuple[float, float]

class Pnt (NamedTuple):
     x: float
     y: float

     def __add__(self, other: PNT) -> Pnt:
     return Pnt(self[0] + other[0], self[1] + other[1])

=-=-=-=-=-=-=-=-=-=-=-= >8 =-=-=-=-=-=-=-=-=-=-=-=-=

But when I import this, I get the following diagnostic:

Traceback (most recent call last):
   File "", line 1, in 
   File "/home/sisc/projecten/iudex/problem.py", line 10, in 
     class Pnt (NamedTuple):
   File "/home/sisc/projecten/iudex/problem.py", line 14, in Pnt
     def __add__(self, other: PNT) -> Pnt:
  ^^^
NameError: name 'Pnt' is not defined. Did you mean: 'PNT'?


Can someone explain what I am doing wrong?


What happens when the advice is followed?

Not sure why declare type-alias and then don't use it, but if insist on 
using class-name will be making a "forward-reference" (because class has 
not yet been fully defined) - see 
https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html#forward-references


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Too Broad of an exception

2023-10-25 Thread dn via Python-list

On 26/10/2023 04.49, rsutton via Python-list wrote:

On 10/25/2023 11:06 AM, Stefan Ram wrote:

r...@zedat.fu-berlin.de (Stefan Ram) writes:

outer quotation marks) prints some prominent exception types. After

...


   "Manually removing" above was meant to be a fast first pass,
   where I only excluded exception types that were obviously
   inappropriate. It is now to be followed by a search for the
   appropriate exception types among those exception types left.



@Rene & @Stefan,
I really appreciate the guidance provided.  By replacing Exception with 

...


It would appear that (at least one message) did not make it to email - 
neither to the list-archive.


People wishing to learn are unable to benefit a response, if it is not 
sent to the list!


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Checking if email is valid

2023-11-01 Thread dn via Python-list

On 02/11/2023 00.35, Simon Connah via Python-list wrote:
OK. I've been doing some reading and that you should avoid regex to check email addresses. 


This operation used to be a BIG THING back in the days of 'everyone' 
building PHP web-sites. When there were only a handful of TLDs 
(top-level domain names, eg the country-codes* such as .nz and .uk plus 
the generics such as .com and .net. Accordingly, one could hold the 
entire list for convenience of checking. However when IANA (the outfit 
responsible for the Root Zone Database and especially ICANN realised 
that there was money to be made, they allowed more and more TLDs. 
Keeping-up became a rat-race!


Indeed, I've held another .info domain for twenty years, and used to 
suffer for my 'bleeding edge' daring - quite recently someone (who 
should remain name-less, and a few other less-es) sent me an email 
telling me how to log-in, but their log-in process wouldn't accept the 
'illegal' address. Um...


All together now: "a little bit of knowledge is a dangerous thing"!


So what I was thinking was something like this:


if type(email_recipient) != email.message.Message:

I just don't know why that particular line isn't working.


Will need more context. What is the objective? What is the 
source/pre-processing of these data-items. (etc)




* Left-out .au, (a less important geo-TLD) to wind-up @Chris...

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Checking if email is valid

2023-11-02 Thread dn via Python-list

On 02/11/2023 19.46, Simon Connah via Python-list wrote:

On Thu, 2 Nov 2023 at 05:21, Simon Connah via Python-list
python-list@python.org wrote:




Could someone push me in the right direction please? I just want to find out if 
a string is a valid email address.









There is only one way to know that a string is a valid email address,
and that's to send an email to it.




What is your goal though? For example, if you're trying to autolink
email addresses in text, you don't really care whether it's valid,
only that it looks like an address.




My goal is to make a simple mailing list platform. I guess I could just send 
email to an address and if it bounces then I can remove it from the database. 
Thing is I'm not sure how close to a real email address an email has to be in 
order to be bounced. If it was completely wrong it might just swallowed up.


Exactly!

Build a complementary script which inspects the returned/bounced 
messages, and removes those addresses.


Given that the list of addresses is built from people signing-up in the 
first place, one has to presume that people know their own addresses and 
can type - there's no real defence against 'stupid'*. It's not as if you 
are making-up addresses yourself (in many jurisdictions it is illegal 
without opt-in).


An email address: account@domain, has to be accurate in two ways:
1 the domain - otherwise the DNS (Domain Name System) won't be able to 
locate the destination email server
2 the account - otherwise the email server won't know to which mail-box 
the message should be delivered.


The (1) is why there was some suggestion of using MX records (but may as 
well just send the message).


The problem with (2) is that some servers will 'bounce' a message, but 
others will let it die silently (not wanting to add to email-spam by 
sending stuff 'back' if the message was spam in the first place!)


The exception to (2) is a "catch-all" address, which accepts every 
message not addressed to a (legal) mail-box. These are sometimes used to 
deal with messages addressed to a staff-member who has left (for 
example). However, are somewhat problematic because they pick-up tons of 
garbage (eg earlier today I received a message to 456...@domain.tld. 
This is not, and never has been, a mail-box on the domain; but would 
drop into a catch-all mail-box.


It would be an unusual MailAdmin inspecting a catch-all address, who 
would return a mis-addressed email to its source. If the message was 
addressed to s...@domain.tld, I'd be more likely to assume it was for 
you, and forward it to you (in the expectation that you'd fix the 
problem with the sender...). However, ...


There are some large businesses doing what you've outlined. They have 
not solved this problem - and not through lack of trying!



* as fast as you make something idiot-proof, the world will show you an 
'improved' class of idiot!

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Checking if email is valid

2023-11-02 Thread dn via Python-list




On 02/11/2023 19.56, Chris Angelico via Python-list wrote:

On Thu, 2 Nov 2023 at 17:47, Simon Connah  wrote:


My goal is to make a simple mailing list platform. I guess I could just send 
email to an address and if it bounces then I can remove it from the database. 
Thing is I'm not sure how close to a real email address an email has to be in 
order to be bounced. If it was completely wrong it might just swallowed up.



Every address is completely separate. There is no "closeness". Just
send email to an address.



Agreed.

However, with names that are frequently misspelled or which are 
commonly-spelled slightly differently, the 'trick' is to anticipate 
problems and set up aliases which forward messages to the correct address*.


eg Kelvin -> Kevlin
Niel, Neal, Neale (etc) -> Neil

(in the same way that GoodLookingGuy@mydomain -> me,
or (more likely) MailAdmin -> me)


* however, this can end-up perpetuating the mistake, rather than 
correcting...


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Checking if email is valid

2023-11-02 Thread dn via Python-list

On 02/11/2023 20.28, Simon Connah wrote:


I'm not sure that would be practical. As I'm setting up a mailing list server I 
don't know if someone in the future is going to need to use one of those 
aliases and testing manually would be tedious.


Please re-read.
Discussion is about "closeness".
Thus, what you might expect from email servers and Admins, NOT what you 
should do. That part should be quite evident by now!


--
Regards,
=dn

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


Safe package removal

2023-11-05 Thread dn via Python-list

After thread: "pip/pip3 confusion and keeping up to date"


Over the years?centuries, have added various packages, using all of:

- distribution-installer (dnf/yum - per apt-get)
- su pip install, and
- (user) pip install

Because Fedora-Linux can be upgraded in-place. an amount of 'crud' 
hangs-about 'forever'.


Accordingly, python -m pip list --outdated shows about as many entries 
as python - m pip list!


Have (comparatively recently) standardised that projects not inside a VM 
or Container, will be managed by Poetry. (It's working well!)



Q1
Can all (user) pip installs be safely removed, 'just like that'?

Q2
How can one ascertain if system (su/sudo) pip installed packages can be 
removed - or are used by the op-sys/some important application?


Q3
Similarly, if one can uninstall those originally installed using the 
distribution-installer, or if something, somewhere, will 'break'?

(yes, there's an upgrade to Fedora 38 in "The Backlog")

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: fCONV_AUSRICHTG is not defined - Why?

2023-11-07 Thread dn via Python-list

On 08/11/2023 06.47, Egon Frerich via Python-list wrote:

I've no idea why this happens. In a module there are lists and definitions:

...


     ["%s%s%s " % (i[fCONV_AUSRICHTG], i[fLG2], i[fTYP]) for i in Felder])
   File "/home/egon/Entw/Geldspur/geldspur/gui/GUI_Konfig.py", line 90, 
in 

     ["%s%s%s " % (i[fCONV_AUSRICHTG], i[fLG2], i[fTYP]) for i in Felder])
NameError: name 'fCONV_AUSRICHTG' is not defined

You see "Felder" and with "0 0 3 4" the correct value 4 for 
fCONV_AUSRICHTG. But there is the NameError.


What does  mean? Is there a change from python2 to python3?


Works for me (Python 3.11 on Fedora-Linux 37)
- both as a script, and simple/single import.

What happens when you extract the second dimension's definitions into a 
module of their own, and import that (with/out less-sophisticated join)?


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Clearing the Deque • Picturing Python’s `deque` data structure

2023-11-07 Thread dn via Python-list
You will be welcome to join us at our next (hybrid) meeting: Wednesday, 
15 November 2023, 1815~2030 NZDT (0515~0730 UTC).



How often do you use a deque*? “Not very” is a common answer. Perhaps 
you’ve never used it. In this presentation, Stephen won’t try to 
convince you to use it more often. Instead, he’ll present a different 
perspective on what this data structure is, and how it differs from a 
list. The presentation will compare deques and lists in a visual manner, 
to help us understand why we may need a deque in certain situations. 
We’ll also explore some demonstration examples to highlight the 
differences in performance between the two data structures in different 
scenarios.

*pronounced like “deck"

Audience: This presentation is ideal for those who have either never 
heard of deque, or have heard of it but never really used it or 
understood why it’s needed. The more experienced may find the visual 
story insightful.


Stephen used to be a physicist, which is where he learned programming. 
After working in science and academia for over a decade, he decided to 
escape before it was too late. Since then, has focused exclusively on 
teaching coding and communicating about Python. A big part of his day is 
busy with running Codetoday—we teach Python coding to children between 7 
and 16 years old (https://www.codetoday.co.uk/). He also runs courses 
for adults and corporate training programs, and particularly, writing 
about Python. He writes the articles he wished he had when learning. He 
publishes articles at The Python Coding Stack 
(https://thepythoncodingstack.substack.com/) and also wrote an online 
book (soon to be in other formats, too) for beginners, The Python Coding 
Book (https://thepythoncodingbook.com/).



Please RSVP on Meetup.com (NZPUG Auckland Branch): 
https://www.meetup.com/nzpug-auckland/events/295433874/


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Newline (NuBe Question)

2023-11-15 Thread dn via Python-list

On 15/11/2023 20.25, Grizzy Adams via Python-list wrote:

Hi & thanks for patience with what could be simple to you

Have this (from an online "classes" tutorial)


There are lots of on-line classes!



--- Start Code Snippit  ---

students = []
grades = []
for s in geographyClass:
students.append(geographyStudent(s))
for s in students:
 grades.append(s.school)
 grades.append(s.name)
 grades.append(s.finalGrade())
 if s.finalGrade()>82:
 grades.append("Pass")
 else:
 grades.append("Fail")
print(grades)

--- End Code Snippit  ---

I have extended (from tutorial) it a bit, I would really like to have a newline

at end of each record, I have searched (and tested) but cant get "\n" to give a

newline, I get "Mydata\n"

Do I need to replace "append" with "print", or is there a way to get the
newline in as I append to list?


Don't know how "Mydata..." results - where is it in the code.

What do you see when grades is printed?
Do you really want data-values all mashed together?

Yes, what changed after removal of all the .append()-s, and instead, 
within the (second) for-loop print( school, name, ... ) was used?


Is it easier to go on from there?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


NZPUG Mtg: Making Python faster, and "Dependency Inversion"

2023-11-22 Thread dn via Python-list

Virtual meeting: Wednesday 6 December, 1815 for 1830 NZDT/UTC+13
Book at https://www.meetup.com/nzpug-auckland/events/295433876/


1 Making Python faster - using type hints

Tushar will lead us through:

A brief history of type hints
Using type checkers to verify your type hints
Compiling type checked Python to make it faster
Some examples of libraries and the speedups they get from type hints

We'll be looking at mypy/mypyc.

Audience Level: intermediate, ie understand Python constructs, 
functions, control flow, etc.


Tushar has been a long term Python developer, OSS contributor, author 
and speaker. He has been working with static analysis and type checkers 
for the past 3 years, and has contributed to various PSF-projects such 
as black and mypy.



2 SOLID's Dependency Inversion Principle

Olaf will complete the current Software Craftsmanship series on the 
SOLID Principles with a session on the Dependency Inversion Principle. 
This one is particularly fascinating, because at first-glance the 
inversion seems to be asking us to do things backwards. With 
understanding, we realise that it is an impressive device enabling us to 
focus on what is needed by the 'layer' of more valuable components, 
rather than the lower-level, eg UIs and external interfaces (need 
refresher? see https://www.bmc.com/blogs/solid-design-principles/)


Audience Level: advanced, ie understand programming constructs, 
patterns, principles, etc.


Olaf needs no introduction having generously brought us the earlier 
sessions in his "Software Craftsmanship" series over the last two years. 
Let's complete this exercise in dogged-persistence and round things off 
neatly - if you remember, this talk was originally scheduled last month, 
but technical-gremlins got in the way! Also, please tell us what topics 
you'd like to cover at this skill-level in future...



Please come, and come with a collegial frame-of-mind. Questions and 
conversation will be the order of the day. If you are more confident in 
Python, your constructive advice, suggestions, and alternate approaches 
will be valued ...


--
Regards =dn
--
https://mail.python.org/mailman/listinfo/python-list


FridayFinking - Was: A beginning beginner's question about input, output and . . .

2021-01-13 Thread dn via Python-list
On 14/01/2021 04.54, Grimble wrote:
> On 11/01/2021 20:37, DonK wrote:
>>
>> Hi, I'm thinking about learning Python but I'm 74 years old and will
>> very likely not ever have a programming job again. 

> At 83, I have no intention of having a programming job again! I last
> coded something professionally 45 years ago, but it hasn't lost its
> attraction.

Hey, some 'silver surfers' who have a few years on me!

Concerning the definition of "old"
- when I'm having a 'good day', it's anyone several years my senior (and
above)
- when I'm creaking and groaning, it's anyone remotely my age, and older.


Of course, many of my colleagues have fairly similar understandings -
for them anyone with the digit "3" (or greater) at the front of their
age, is not so much old (saying that would be rude!), but "ancient"!


That said, such young-bucks wrestling with cloud-concepts today, were
totally nonplussed when I told them how (mainframe) computer bureaux
used to work. The 'mechanics' may be different, but the management is
little-changed!


...

> I find this a fascinating news group - shame there's been no updates to
> Friday Finking recently!


With all due apologies!

I work(ed) with a particular team in a mentoring rôle, handling reviews,
walk-throughs, some design meetings, Python version-upgrades coaching,
etc. One of these was a 'morning tea' meeting, when we would
discuss/debate/argue 'Python best practice' topics, either raised by
members or that arose from other meetings but were best not discussed
there-and-then.

If there was an interesting topic, or one that 'we' hadn't really
settled satisfactorily within the group, I would try to re-frame the
discussion, and consult 'the oracles' here. So, that's the raison d'être
and motivation of the "Friday Finking" series..


Then along came COVID-19, and although this country's response was
amongst the best in the world, the team (and its routines) all-but
fell-apart. Firstly, we had to adjust to working remotely. The effort
that went into 'Friday Finking' was quickly absorbed into figuring-out
remote-techniques and maintaining the social component of the team's
success. Then a bunch of us were 'released to other duties' and
landed-in high-pressure projects to do with modelling pandemic
response-options. Various other interventions, life moved-on, etc, etc -
stories familiar to most, I'm sure.


So, thank you for the gentle reminder. Even though that team is still
not meeting as it once did, there's plenty of other 'inspiration', eg a
parallel discussion 'here' about the virtues of a programmer positioning
dialog(ue)s/windows or leaving it to the window manager...


I'll give it some thought - as long as Fridays keep coming!
-- 
Regards =dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Application window geometry specifier

2021-01-13 Thread dn via Python-list
On 14/01/2021 15.25, boB Stepp wrote:
> On Wed, Jan 13, 2021 at 7:28 PM Chris Angelico  wrote:
> 
>> I love how "I think" is allowed to trump decades of usability research.

I'm just pleased that @Chris has found love!
(not detracting from the point though)


> Can you recommend a good reference for someone relatively new to GUI
> programming that is based on such research?  Book or web reference
> would be fine.

Most of my training-materials (certainly in this topic) are web-based -
but the ideas are also common to Python.


Nielsen-Norman Group do a lot of work in UX and offer a regular
newsletter which is usually a good way to make the brain-cells work for
their living: https://www.nngroup.com/

eg https://www.nngroup.com/articles/usability-101-introduction-to-usability/


A more applied view, courtesy of the New Zealand Government:
https://www.digital.govt.nz/standards-and-guidance/nz-government-web-standards/web-usability-standard-1-3/


Some become confused between the two terms: Accessibility and Usability.

Here's what the boss says:
https://www.w3.org/WAI/fundamentals/accessibility-usability-inclusion/

This article clearly explains each and then offers a comparison.
https://www.telerik.com/blogs/web-accessibility-vs-usability


If you really want to dig-down, I know for-sure that IBM, Microsoft,
Apple (and presumably others) have compiled style-guides about how
various GUIs should work, starting from really basic matters such as
when to use radio-buttons and when check-boxes. I can't tell you if the
gtk, qt, or wx people offer something similar...
-- 
Regards =dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Friday Finking: Abstract Base Classes - love or hate

2021-01-14 Thread dn via Python-list
Do you make frequent use of Abstract Base Classes (ABCs), prefer to use
an ordinary super-class for the same purpose, or steer-clear? Are they
more-usually employed when the project includes an extensive design
stage, and the meta-class integral to some hierarchy of entities?


Previous Friday Finkings have arisen from in-house discussions within a
Python dev.team which deserved a wider airing or debate. This contains
(with due apologies) excessive personal reflection and comments
abstracted from posts to this Discussion List.


Many of us have used Python for years but never touched ABCs. Apparently
then, we don't need to be aware of them! Colleagues 'here' have said
"never used it" and/or "never seen the need", and similar.

Often pythonista learn how to define class(es), and then to inherit or
compose further classes. Everything works swimmingly. If it ain't broke,
don't fix it! So, we have no reason to advance our programming
capabilities/knowledge. Indeed an earlier post voiced the suggestion
that we could get on quite happily without knowing about/using ABCs.


Aside: Certainly the earliest iteration of Python meta-classes/ABCs
(related, but confusingly different - am not going there!) 'arrived' at
about the same time as did I - back at Python 1.n - but I've only
ever/started using ABCs, since circa 3.5. Thus, from personal
learning-experience: one can only understand and use abstract-classes
after gaining a thorough understanding and facility with using
(ordinary) class-es. (perhaps?)


Conducting (what some people call) extensive research*, we will be told
that an ABC is: "a way to overload isinstance() and issubclass()". When
would we use those two functions which introspect a class-hierarchy?

isinstance(object, classinfo)
= is the object argument an instance of the classinfo argument

issubclass(class, classinfo)
= is the class argument a subclass of the classinfo argument
(etc)

Luv-a-duck! How does this fit with duck-typing and EAFP? (sorry,
terrible attempt at a joke) Aren't we supposed to *presume* that we our
sub-class/instance is just that, and we should just presume to use its
data and methods (wrapped in a try...except in case 'forgiveness' might
be necessary)?


Perhaps with the increasing number of DataScience folk using Python (?),
we do seem to be finding a reasonable proportion of Python
improvements/updates seemingly heading in the LBYL direction... OK,
let's go-with-the-flow.

There are two 'problems' with the isinstance()/issubclass() approach:
- it's not very duck-y
- when it 'happens'.

So, let's say we want to *execute* a particular method against the
current data-structure. We can only do this if the class (or its
hierarchy) includes said method. Thus:

data.method( arguments... )

However, we are concerned that the instance may not be part of a
hierarchy offering this method. What can we do?

- EAFP: wrap in try...except
- LBYL: check for method by assuring the hierarchy, eg isinstance()

Each incurring the consequential-problem: but what then?


The problem is not 'discovered' until execution-time - worst-case
scenario: it is discovered by some user (who is no-longer our friend).

If we are really going LBYL, surely we want to discover the problem as
early as possible, ie preferably whilst coding+testing?

Using an ABC we can do just that, because the presence/absence of
methods is checked when the sub-class is defined. If it does not
implement all of the required methods, the sub-class will fail. Yes, we
could do that by coding a super-class with methods that contain only:

raise NotImplementedError()

but when would a sub-class's error in not implementing the method then
be 'discovered'?


Personal aside/illustration/confession: I implemented an application
which used "plug-ins" - effectively filters/actions. The first couple of
use-cases were easy - they were integral to the application-design. As
is the way of these things, few months later a request arrived for
another plug-in. Of course, I was very happy with the plug-in which I
coded oh-so-quickly. Trouble is, I *forgot* to implement one of the
required methods, and mis-spelled another. Yes, if I had a scrap of
humility, I should have re-read my original code. Sigh!

Forget the apocryphal "will your future self remember in six months'
time", as I have aged (and most of us do!), I've moved my philosophy to
one of trying to avoid having to remember - firstly in six *weeks'*
time, and more recently: six *days'*!

All was greatly improved by implementing an ABC as a guide, or a
check-list, even, a template - as proven by later requests for yet more
'plug-ins'...

Please remember that 'umble scribe is not an "OOP-native", starting this
career way-back when mainframes were powered by dinosaurs in
tread-mills. I am told this is what other languages refer to as an
"interface". In some ways I visualise the ABC as a "mixin" - perhaps
better-understood when the ABC does include an inheritable method.
(feel free to add/d

Re: why sqrt is not a built-in function?

2021-01-15 Thread dn via Python-list
On 16/01/2021 10.49, Michael F. Stemper wrote:
...

> Es ist Feierabend


You had me there for a moment, because spotting a 'double meaning"
(actually triple) my mind succumbing to dissonance, refused to translate
(into English), instead latching onto the last two syllables:-

At one time, tech-jargon included the term "abend". It meant "abnormal
end", and was a more palatable term (to someone) for "crash" - a bit
like the airline which talked of "non-operational termination" instead
of using the same (unpalatable) word!


Yes, not only might it have been literally the end of (your) day. This
conversation does seem to have reached the point of reductio ad absurdum!
-- 
Regards =dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: why sqrt is not a built-in function?

2021-01-15 Thread dn via Python-list
On 15/01/2021 06.44, Denys Contant wrote:
> I don't understand why sqrt is not a built-in function. 
> Why do we have to first import the function from the math module?
> I use it ALL THE TIME!
> 
> That felt good. Thank you.


Are you 'venting', or do you have a specific frustration-induced question?


Much of my training work centers on HTML5. An issue which you will have
experienced as a user (if not an HTML5 coder), is how long it takes for
certain pages to load or to respond to a 'click'.

We talk of the "weight" of the page. Sadly, in a bid to "capture
eye-balls" and/or to prove how much smarter 'I' am (than any other
web-author/JavaScript-er), there are (far too) many reasons why
web-pages are adorned and accompanied by myriad scripts (and likely,
whole libraries/frameworks), and thus become slow (or 'heavy').


What does this have to do with Python?

As an "interpreted language" Python will (tend to) execute slowly when
compared with a "compiled language".
(ignoring 'shades and grades', and purity of definition)

Another form of delay/slow-ness, is how long it takes a program(me) to
start (in the eyes of the user). Another form of 'weight', and component
of start-up time is how much storage is required to hold the code
(excluding any data).


An advantage of Python is that it has a small 'core'. Mark Summerfield
(author) refers to it as "Python's beautiful heart". The minimised core
(or should that be "optimised"?) is fast to load, and occupies minimal
resource.

As a consequence, you and I may well grumble that we have to import the
math library - every time we code some non-trivial calculation. However,
in doing-so we (should) compute a conscious cost-benefit analysis:
knowing that to include the library will incur a resource-cost, but that
its facilities will improve the accuracy and/or efficiency (eg speed) of
our work. OK, so sign me up!

Contrarily, people who don't 'work with numbers', eg other threads
'here' discussing character manipulation; don't experience any longer
waiting-time or 'suffer' extra resource-cost, due to loading the math
library, from which they/their code will receive no benefit at all!


Thus, one of the philosophies of Python I keenly appreciate (that makes
me "[feel] good", to borrow your words), is that not only are "batteries
included", but I don't have to carry-around any 'spare batteries' that I
don't actually need right now!

(even more applicable when using MicroPython, etc)
-- 
Regards =dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: why sqrt is not a built-in function?

2021-01-15 Thread dn via Python-list
On 16/01/2021 11.40, Michael F. Stemper wrote:
> On 15/01/2021 16.01, Chris Angelico wrote:
>> On Sat, Jan 16, 2021 at 8:56 AM Michael F. Stemper
>>  wrote:
>>>
>>> On 15/01/2021 15.26, Stefan Ram wrote:
 "Michael F. Stemper"  writes:
> On 15/01/2021 14.01, Stefan Ram wrote:
> 
>> __import__( "math" ).sqrt( 4 )
> I had no idea that syntax existed, and find it completely at odds
> with The Zen of Python. I'm torn between forgetting that I ever saw
> it and using it for some evilly-obfuscated code.

     When one collects snippets of Python code that are intended
     to be inserted into programs, a snippet usually would have
     to consist of two parts: One part to be inserted at the top
     of the program, into the imports section, and then the actual
     snippet.
     "__import__" allows to write snippets that can be inserted
     as they are without the need to do insertions at two different
     places. (Possibly with a tool to later normalize the insertions
     to the usual style.)
>>
>> I'm not sure how that works. In Python, you can just put the imports
>> where you want them - why would the __import__ function be needed?

import is 'syntactic sugar' for __import__().

Have you not heard that "sugar is the new smoking"? We're being
encouraged to cut-back or giving it up completely...


More seriously, it's like creating a class object by

MyClass = type('MyClass', (), {})

whereas it's far easier (for most of us) to use

class MyClass( etc )

However, when the power and/or dynamic possibilities of the underlying
code-construct is/are required...


> I have no idea what PEP-8 has to say on the subject. However, my coding
> style *generally* puts all of the imports up front, right after the
> prologue (program description, revision history, uzw).

This is indeed received-wisdom.

However it does not disallow (yuk: double-negative!) coding an import
statement elsewhere, eg a routine which is only executed during some
invocations, but not others.


What you may like to consider about "prolog[ue]s" is whether they belong
'in' the code (plenty of arguments 'for') or within the VCS (plenty of
arguments here too)...

eg1: how easy is it to establish when a particular decision/code-change
was made (more than one week ago)? - particularly if changes were
subsequent made 'on top of' that change?

eg2: is it a good idea to use 'Python constants' to display the
program(me) name and (perhaps) a version number on the
terminal/application window?


>> I am confuzzed.
> 
> It's a common condition.

There are three components:
1 From the Greek: "con" meaning 'against' or 'unable'.
2 From tech-jargon (and the Australian habit of shortening every word in
the English language): "fuzz" is the contraction of two highly-technical
terms, famously applied in intro courses and by naive job-interviewers.
3 From English: the suffix "ed" meaning past tense.

Thus, (smirking!) "confuzzed" is the psychological term for people who
have never been able to bend their minds around the "fizz-buzz" coding
challenge.


PS am running for cover before @Chris reads this...
-- 
Regards =dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: open sentinel-2image python

2021-01-17 Thread dn via Python-list
On 18/01/2021 08.12, omid mohammadi wrote:
> On Sunday, January 17, 2021 at 9:31:58 PM UTC+3:30, MRAB wrote:
>> On 2021-01-17 13:57, Karsten Hilbert wrote: 
>>> Am Sun, Jan 17, 2021 at 02:20:24AM -0800 schrieb omid mohammadi: 
>>>
 When I open the sentinel-2 image in Python, I get the following error: 

 MemoryError: Unable to allocate 115. MiB for an array with shape (5490, 
 5490) and data type float32 

 How can I fix it? 
>>>
>>> You can install more RAM. 
>>>
>> Or maybe the OP is running 32-bit Python but the code needs >2GB. If 
>> that's the case then using 64-bit Python might fix it, assuming that 
>> it's a 64-bit machine.
> 
> Yes, it is 64.
> 
> Excuse me, can you explain how I can fix it?


What is "64" - the machine or the Python package?

>From where did  you download Python?

What is the code being used to read/load the image?

What do you mean by "the sentinel-2 image" - most of the images (which I
spotted in a *quick* survey) made available to the general public are of
the order of tens of mega-bytes. (a URL might help people trying to
replicate the problem!)


Be advised that everyone 'here' is a volunteer. Please help us to help you!
--
Regards =dn

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


Re: Response for PING in ircbot.

2021-02-03 Thread dn via Python-list


On 04/02/2021 07.07, Dennis Lee Bieber wrote:
> On Tue, 02 Feb 2021 20:26:34 -0500, Random832 
> declaimed the following:
> 
> 
>> 1. It looks like you're forgetting to send \n\r
> 
>   Isn't the convention \r\n -- from the days of teletype, when the return
> took longer to complete than the line feed, so start return, have it finish
> while the line feed activates...

Yes, "CRLF" = Carriage Return (chr( 13 )) and Line-Feed (chr( 10 )).


>   The order didn't matter in the .strip() call as that strips any
> leading/trailing characters that match any of the provided set, it is not a
> "trim" of the exact sequence (hmm, looks like that would be require using
> string.removeprefix("\n\r").removesuffix("\n\r") if the expected sequence
> were such).

If every line ends with the same (odd) suffix, then why not slice the
string [ :-2 ]?

Alternately, consider str.translate() where both character codes are
removed, regardless of location.
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Selenium finds object that is interactible but says otherwise

2021-02-06 Thread dn via Python-list
On 07/02/2021 08.21, Philipp Daher via Python-list wrote:
> Hello,
> 
> 
> I recently programmed some code for a webdriver with selenium.
> I asked the program to find an input tag, which is interactible, with this:
>    
> searchbar=driver.find_element_by_class_name("ut-player-search-control--input-container")
> 
> then i ask it to send keys, which has worked before too. But this is the
> message I get.
> And yes, i have checked, the input tag is the only tag with that class
> name, so there isn´t another tag which selenium could´ve interacted with.

This mailing list strips many attachments. Please copy-paste.

First step is to check the target HTML-page to ensure it does actually
have a class of that name.

Whilst used by many CSS-tools, is the double-dash/hyphen intended?
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Python cannot count apparently

2021-02-07 Thread dn via Python-list
On 08/02/2021 09.49, Kevin M. Wilson via Python-list wrote:
> Set i = 0 at the begin of the code, that way each entry starts at Logical 0 
> of the array/container/list...


FYI: https://docs.python.org/3/library/stdtypes.html#typesseq-range

See also @Chris' contribution regarding the pythonic idiom for iterating
over a container.
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Fwd: Inconveniente

2021-02-09 Thread dn via Python-list
On 09/02/2021 15.13, Juan Jose Reyna Figuera wrote:
> *Buenas tardes, le escribo breve y puntualmente para reportar este el
> siguiente error al cual no le pude dar solución.*
> 
> *Instalé Python 3.9.1 (64 bits), todo había funcionado bien hasta que
> necesité usar la librería seaborn. Al ejecutar mi algoritmo obtenía el
> siguiente error: *
> 
> (...\Python\Python39\site-packages\matplotlib\__init__.py)
> 
> * Desinstalé python, lo reinstalé.
> * Instale diversas versiones de Matpltlib
> * Desinstalé seaborn, lo reinstalé.
> 
> Busque soluciones en la página oficial, foros como:Stack Overflow, reddit,
> etc y no pudé dar con la solución para esta versión de python.
> 
> Al final instalé python 3.8 de 32 bits, con las librerías que necesitaba, y
> logré realizar el trabajó.
> 
> Mi OS es Windows 10, 64 bits.
> 
> Sin más por el momento,
> 
> me despido cordialmente.


Well done for solving the problem!

[ Translation:
matplotlib (and seaborn) not playing-nicely with Python 3.9 64-bit
edition on MS-Win 10. Solved by down-grading to Python 3.8 32-bit.
]


Yes, there have been problems with certain libraries that have not (yet)
been updated to run on Python 3.9. Your solution is the current advice.

However, I'm concerned about mathematical applications on 32-bit
platforms. Did you try Python 3.8's 64-bit option (plus libraries)?


NB this is an English-language list - for faster response to questions.

[Cordialmente]
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: installation issues

2021-02-09 Thread dn via Python-list
On 10/02/2021 12.23, Martin Lopez wrote:
> Hello,
> 
> My name is Martin Lopez. I just downloaded Python 3.9.1 (64 bit) Setup.
> 
> After I install the program then try to run it, with no success.
> 
> I've uninstalled all previous versions and reinstalled them, but it does
> not seem to help.
> 
> Can you please assist?


Welcome to the mailing list Martin!
Please also note that there is a Python-Tutor list expressly for
Python-learners.


Answers vary according to which Operating System is in-use!


Useful Web.Refs:

https://wiki.python.org/moin/FrontPage (particularly the Beginner's Guide)

https://www.python.org/doc/ (for everything, but start with "Using Python")
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New Python implementation

2021-02-11 Thread dn via Python-list
On 12/02/2021 07.14, Mr Flibble wrote:
> On 11/02/2021 18:06, Chris Angelico wrote:
>> On Fri, Feb 12, 2021 at 5:01 AM Mr Flibble
>>  wrote:
>>>
>>> On 11/02/2021 16:31, Dan Stromberg wrote:
 On Thu, Feb 11, 2021 at 4:35 AM Mr Flibble
 
 wrote:

> I am starting work on creating a new Python implementation from
> scratch
... (which isn't a stretch given how poorly they perform).

 I'd like to encourage you to give this a go.  It's a huge task, but
 it's needed.
>>>
>>> Actually it is a relatively small task due to the neos universal
>>> compiler's architectural design.  If it was a large task I wouldn't
>>> be doing it.
>>>
 You may be interested in...
>>>
>>> I am not particularly interested in any of the existing
>>> implementations as they bear no relation to the design of my language

...not being standardized; those steering
>>> the language need to grow a pair and get Python standardized
>>> preferably as an ISO Standard.
...
> For a language to transition from "toy" status it has to be formally
> standardized.  It is unacceptable to define a language in terms of a
> particular implementation. A git repo of Source code and associated
> observable dynamic behaviour when that code is compiled and ran is a
> poor substitute for an official ISO Standard.
> 
> /Flibble


When I first met it, one of the concepts I found difficult to 'wrap my
head around' was the idea that "open software" allowed folk to fork the
original work and 'do their own thing'. My thinking was (probably)
"surely, the original is the authoritative version". Having other
versions seemed an invitation to confusion and dilution.

However, as soon as (open) software is made available, other people
start making it 'better' - whatever their own definition of "better".

Yes, it is both a joy and a complication.


Such is contrary to the principle of "standards". At its extreme, a
standard says there is only one way to do the-whatever. This is why many
'standard programming languages' then offer the 'out' of having various
levels of 'standard'. For example, despite being one of the longest
standardised languages, many COBOL implementations achieve only part of
"the standard" - and one has to dive (deep) into the 'small print' to
establish which 'bits' are in their particular 'pick and mix'. Yet, they
still (quite legally) refer to their product as 'standard'!

The second issue with standards is the time and effort it takes to
achieve an agreement and thus reach the point of publishing.

A third issue, and possibly the reason why attempting a standard is a
"losing battle", is that programming and languages are in a constant
state of flux - we call it "ongoing development". Even though Python
v3.10 is reaching a state of anticipation, there are organisations and
libraries that still work using Python 2. Thus, and HTML/"the browser
wars" is an example of this, as fast as a standard is discussed, someone
(even those contributing to said standards) is doing his/her best to
build 'more advanced features' beyond the standard... "Standards" and
'driving development forward' are at least in tension, at worst,
complete-opposites.

Standards, like "waterfall" project specifications, cannot be 'cast in
stone' because the world keeps changing. Standards are insufficiently
agile and Agile!


Whereas the likes of COBOL had "owners", if not as a point-of-fact, at
least in terms of (commercial) 'might' and 'power', Python has its
"Python Software Foundation" (https://www.python.org/psf/). Please feel
free to approach that group to talk about 'what is Python' and
'standardisation'.

Rather than a process of "imposing" a standard, Python has a more 'grass
roots' democratic process which involves PEPs (Python Enhancement
Proposal). These are 'great ideas', even intentions-to-build or
proofs-of-concept, documented, and presented for the community to
consider. The better ones make it through and become part of the
language and its eco-system.

Has the above proposal started on that 'standards path'? Is it
'documented', or merely an idea?


Another aspect of open source is its 'meritocracy' - respect for those
who have demonstrated their abilities (and commitment). Certain names
'crop-up' on PEPs, and more tellingly, on "accepted" PEPs.

Of the three names appearing in this thread, which two have been seen
before, and have contributed to PEPs or to this list, in the past?

Is there a choice to 'stand on the shoulders of giants', or to 'walk all
over ... in hob-nailed boots'? Has this conversation illustrated
respect, or (perhaps unintentionally) torn-down others' sweat-and-tears
without offering something (better) for consideration/approval/use? Is
there any proof that you/I/someone-else can actually "do" better? An
applicable saying is "the proof is in the pudding". So, rather than
claims, shouldn't we be dealing with facts, eg system-A does better than
system-B under the following conditions?


A community comprises people who 

Re: New Python implementation

2021-02-11 Thread dn via Python-list
On 12/02/2021 08.53, Chris Angelico wrote:
> On Fri, Feb 12, 2021 at 6:47 AM dn via Python-list
>  wrote:
>> 3
>> My mind is whirling in an attempt to understand "show me a better time".
>> Does this perhaps indicate that @Chris' social life leaves something to
>> be desired? Are Python-nerds really the ones to turn-to for dating
>> advice, or is that not what @Chris means by "(having) a good time"?
> 
> LOL! I was referring to the fact that my demonstration snippet
> included a rudimentary timing bracket, and that, if existing Python
> implementations are indeed abysmally slow, it should be possible to
> run the same code on a different interpreter and get a lower number -
> a "better" time being shorter.


Agreed.

I've been 'bitten' by running 'the same' interpreter on different
hardware/configs and finding that one part of the program[me] ran faster
on the dev-machine, and another part faster on the prod-box. Felt a bit
like a no-win situation! Timing was an important contribution. However,
needing to perform same in-situ was a surprise. 'Gotcha'!

There are a lot of variables in the efficiency-game. It's not completely
cut-and-dried to say this, but as a general rule-of-thumb one does not
select Python for applications/components which have significant
execution-time constraints/requirements. However, Python is rarely
bettered when it comes to developer-time! Horses for courses...


As to being outrageously cheeky: even if COVID travel-restrictions have
been lifted, knowing the Tasman Sea remains between us,
allowed/emboldened me to go for the prize(?) for finding at least some
word-play to laugh-about in this whole conversation.

PS my version of bravery is that if you come after me carrying a big
stick, I shall run in the opposite direction - very quickly!

PPS speaking of travel: have you taken advantage of any of the
"vouchers" offered by your (Fed?State) government as an economic
stimulus/recovery for the hospitality industry?
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mutating a deque whilst iterating over it

2021-02-11 Thread dn via Python-list
On 12/02/2021 09.22, duncan smith wrote:
> Hello,
>   It seems that I can mutate a deque while iterating over it if I
> assign to an index, but not if I append to it. Is this the intended
> behaviour? It seems a bit inconsistent. Cheers.


Yes, and no! Agree and disagree. (see how decisive I can be?)

Inconsistent when compared with what?


A tuple is immutable, but if it contains mutable objects as elements,
they are mutable. Consistent!


That said, tuples can't be append-ed/extend-ed, so a deque may seem more
like a list than a tuple. A list will allow both element and list mutation.

Substituting a list in the sample code, the iterator will adjust to
include an appended element. Inconsistent!


However... what happens if you have a for-loop which processes a list,
and within the loop one element is mutated in value and another appended
to the list?

Oops!


Maybe the deque authors wanted to avoid that, or perhaps such is related
to the option to bound the length of a deque (by design or side-effect)?
Imagine a bounded-deque (completely 'filled') and the code is
(overly-simple example) printing its contents. If the deque-element
printing-loop also allows deque-mutation, then the first value(s),
previously printed, will no longer exist within the queue.


I'm enjoying the question: wither inconsistency? Perhaps someone (wiser)
will jump in...
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: PSYCOPG2

2021-02-13 Thread dn via Python-list
On 13/02/2021 18.34, Mladen Gogala via Python-list wrote:
> On Fri, 12 Feb 2021 18:29:48 +, Tony Ogilvie wrote:
> 
>> I am trying to write a program to open a PostgesSQL 13 database using
>> psycopg2. All seems to work if I write direct to Python but if I write
>> the script into IDLE it does not work with the IDLE Shell 3.9.1
>> reporting an error of no attribute 'connect'.
>>
>> I have tried many options to try and get this to work.

Please copy-paste the code of at least one of these "options", together
with the full error-listing.

Before using the connect function, the module must be import-ed. Has
this been done?

If so, an error with connect() probably indicates a problem with the
function call, eg locating the database.

- as said, really difficult without seeing any code and the err.msgs
generated!


> It looks like your idle is not using the same interpreter that you are 
> using when writing direct code. Anyway, my advice would be to ditch Idle 
> and use VSCode. It's fabulous.


Would it?

Surely if the issue is 'connecting bits together', regardless one still
has to learn the tool and how it works/expects things to be organised?

So, rather than helping the OP with a Postgres/Python/psycopg2 linkage
problem, hasn't (s)he now been presented with an extra learning load?

Regardless, rather than recommending that people send their
'telemetry/tracking data' to MSFT, why not suggest VSCodium
(https://vscodium.com/) - the same open-source IDE, before any such
'extras' are added.


Disclaimer: I do not use or publish Idle, VS-Code, or VSCodium, and have
nothing to gain/lose by MSFT collecting data about what you are doing
with the help of 'their' product.
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is email.message.get() case insensitive for the header name?

2021-02-15 Thread dn via Python-list
On 15/02/2021 09.50, Chris Green wrote:
> It isn't clear from the documentation. Does email.message.get() care
> about the case of the header it's getting?
> 
> I checking mailing list mails and the "List-Id:" header is a bit
> 'mixed', i.e. it can be List-Id:, or List-ID: or list-id:, will
> email.message.get("List-Id:", "unknown") find all of them?


Case is (should be) irrelevant (as it is for most (parts of) Internet
Protocols).

Rather than the "Zen of Python", when it comes to IPs, "Postel's Law"
applies (https://en.wikipedia.org/wiki/Robustness_principle).

The library docs say it follows such.


Web.Refs:

https://docs.python.org/3/library/email.html
<<<
email — An email and MIME handling package

Source code: Lib/email/__init__.py

The email package is a library for managing email messages. It is
specifically not designed to do any sending of email messages to SMTP
(RFC 2821), NNTP, or other servers; those are functions of modules such
as smtplib and nntplib. The email package attempts to be as
RFC-compliant as possible, supporting RFC 5233 and RFC 6532...
>>>


https://tools.ietf.org/html/rfc6532.html
<<<
3.  Changes to Message Header Fields

   To permit non-ASCII Unicode characters in field values, the header
   definition in [RFC5322] is extended to support the new format.  The
   following sections specify the necessary changes to RFC 5322's ABNF.

   The syntax rules not mentioned below remain defined as in [RFC5322].

   Note that this protocol does not change rules in RFC 5322 for
   defining header field names.  The bodies of header fields are allowed
   to contain Unicode characters, but the header field names themselves
   must consist of ASCII characters only.

   Also note that messages in this format require the use of the
   SMTPUTF8 extension [RFC6531] to be transferred via SMTP.
...
>>>


https://tools.ietf.org/html/rfc5322
<<<
RFC 5322Internet Message Format October 2008

2.2.  Header Fields

   Header fields are lines beginning with a field name, followed by a
   colon (":"), followed by a field body, and terminated by CRLF.  A
   field name MUST be composed of printable US-ASCII characters (i.e.,
   characters that have values between 33 and 126, inclusive), except
   colon.  A field body may be composed of printable US-ASCII characters
   as well as the space (SP, ASCII value 32) and horizontal tab (HTAB,
   ASCII value 9) characters (together known as the white space
   characters, WSP).  A field body MUST NOT include CR and LF except
   when used in "folding" and "unfolding", as described in section
   2.2.3.  All field bodies MUST conform to the syntax described in
   sections 3 and 4 of this specification.
...
>>>
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Mr. Flibble

2021-02-15 Thread dn via Python-list
On 16/02/2021 07.09, Ethan Furman wrote:
> Thank you to those who pointed out this individual to the moderators. As
> Mr. Flibble accurately noted, he is not on the mailing list -- so his
> posts won't be here either.

Appreciating the work you(s) invest on my/our behalf!
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New Python implementation

2021-02-15 Thread dn via Python-list



On 16/02/2021 17.57, Dan Stromberg wrote:
> On Mon, Feb 15, 2021 at 8:52 PM Igor Korot  wrote:
> 
>> Hi, guys,
>> Let me try to throw in another one - PL/1.
>> This guys used to be very popular with the accounting community...
>>
> 
> Actually PL/I is basically proprietary Pascal - from IBM.  My Intro Comp
> Sci classes at the University of Cincinnati were in PL/I, because IBM had
> an office not far from the University, and they liked to hire interns from
> UCinci.  I was told that otherwise the classes would've been in Pascal.


Might a coincidence of location have been conflated with language
development?


PL/I (note the Roman "one") was developed out of the IBM System/360
effort, ie one computer architecture for all types of users (cf
different computers for 'commercial' and 'scientific' clients - which
you can see again today in AWS' range of compute options, for example).
It was to be 'one language to rule them all'.

Initially, it was based on FORTRAN. We joked that it took all of the bad
parts of FORTRAN and COBOL and mashed them into a single ... language.
However, like many such efforts, it attempted to take 'the best' from
many sources (including ALGOL).

Sadly, (maybe) it, like Ada (another attempt to be 'all things to all
men') only ever really existed in a niche market.


Pascal, named after the mathematician and philosopher the French credit
with 'inventing the computer', was developed in the European world -
which even back-then had marked differences in thinking to the American
approach/domination of computing.

Prof Niklaus Wirth published a seminal book "Algorithms + Data
Structures = Programs" (which I seem to have lost, somewhere in the
mists of time). I don't think it gave examples in Pascal, but it did use
a pseudo-code/-language which illuminated various ideas and ways of
developing programmatic solutions. As I recall, it (and Pascal) was very
ALGOL like, and thus heavily influenced by "stack architecture" (cf
IBM's collections of "registers" in an ALU). Certainly the language was
clearly based upon ALGOL-60. Clearly it led to the refinement and/or
development of Pascal.

Pascal's value as a teaching language was that it embodied many aspects
of structured programming, and like Python, consisted of a limited range
of items which could be learned very quickly (in contrast to PL/I's many
'bells and whistles'). Thus, once absorbed, learning attention could be
directed to ComSc/algorithms + data!

Pascal was also very efficient, to compile and to execute, which made it
a competent fore-runner of Micro-Python (etc) in the micro and
single-board computer arenae/arenas.

Without Python, I think I'd prefer to use (an updated) UCSD-Pascal or
Borland Turbo-Pascal to this very day! PL/I, not so much - even on a
mainframe project!
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


  1   2   3   4   5   >