Re: Cprod -- (writing this: itertools.product([0, 1], repeat=N )

2024-05-21 Thread dn via Python-list

On 22/05/24 07:14, HenHanna via Python-list wrote:


How can i write this function Cprod (Cartesian Product) simply?

     (writing this out: itertools.product([0, 1], repeat=N )

The value can be a list or a Tuple.

     cprod([0, 1], 1) => ((0) (1))

     cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1))



This works:

    def cprod(x, c):
     if c==1: return [[i] for i in x]
     Sub= cprod(x, c-1)
     return [i  for F in x   for i in [[F]+R for R in Sub]]


-- Is there another way to write [F]+R ???

    Other ways to improve it?


https://python.readthedocs.io/en/stable/library/itertools.html#itertools.product

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


Data Ethics (Virtual) Meeting

2024-04-10 Thread dn via Python-list

Virtual meeting, Wed 17 April, 1800 for 1830 (NZST, ie 0630 UTC)


Data Ethics

Emma McDonald is the Director of the Interim Centre for Data Ethics and 
Innovation at Stats NZ (New Zealand Government Department of Statistics)


Emma will talk about why Stats NZ is establishing a Centre for Data 
Ethics and Innovation, and why it needs to be set up as a network that 
draws on and leverages knowledge and expertise across relevant work 
programmes and people across agencies. As an initiative, the Centre is 
there to help agencies develop and maintain secure and trusted data 
environments. A large part of this is drawing on a diverse network of 
people who can support the with sharing the importance of data ethics 
being a critical component of data driven technologies.


Will be of-interest to Quants, Data Science, and Machine Learning folk; 
as well as those of us with wider interest in what should/not happen 
with personal, public, and corporate data...


She will be wanting to hear what folk have to say, and is interested to 
recruit competent individuals for hui*, consultations, and the like.


WebRef: 
https://data.govt.nz/leadership/the-interim-centre-for-data-ethics-and-innovation/ 
from which you can access their Work Programme and Guidance developed 
to-date.



Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764076/


* hui is the Te Reo Maori word for meeting or conference
(Te Reo is one of New Zealand's official languages)

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


Re: How to Add ANSI Color to User Response

2024-04-10 Thread dn via Python-list

On 11/04/24 06:50, WordWeaver Evangelist via Python-list wrote:

I have a simple question. I use the following textPrompt in some of my Jython 
modules:
  '\nYour choice is? (A B C D E): ', maxChars=1, autoAccept=False, 
forceUppercase=True)
Is there a way to add an ANSI color code to the end where the conditions are, 
so that the color of the user’s input is of a color of my choosing, instead of 
just white?
Thank you very much in advance.
Kind regards,
Bill Kochman


Haven't tried using any of theses techniques, but may define input() 
color, as well as print():-


How to print colored terminal text in Python
MAR 06, 2024
...
https://byby.dev/py-print-colored-terminal-text

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


Re: Multiplication

2024-04-01 Thread dn via Python-list
The April Fools joke was on those of us who never received/have yet to 
receive @Stefan's OP.




On 2/04/24 08:02, Avi Gross via Python-list wrote:

Is this a April 1 post for fools.

Multiplication with an asterisk symbol is built into python.

The same symbol used in other contexts has other contexts has an assortment
of largely unrelated meanings such as meaning everything when used to
import.


On Mon, Apr 1, 2024, 1:27 PM Piergiorgio Sartor via Python-list <
python-list@python.org> wrote:


On 01/04/2024 10.40, Stefan Ram wrote:

  Q: How can I multiply two variables in Python? I tried:

a = 2
b = 3
print( ab )

  but it did not work.

  A: No, this cannot work. To multiply, you need the multiplication
  operator. You can import the multiplication operator from "math":

  Code example:

from math import *

a = 2
b = 3
print( a * b )


I guess the operator "*" can be imported from any module... :-)

bye,

--

piergiorgio

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



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


Re: MTG: Introductions to PyQt and DataClasses

2024-03-17 Thread dn via Python-list

On 18/03/24 10:02, Jim Schwartz wrote:

Actually, I have a sleep disorder that requires me to keep a constant sleep 
schedule. Thats why I asked.


At a weekend meeting, discussion swirled around topics such as the best 
way to learn/work, how much work we should attempt in one sitting, 
could/should I 'do more', and similar.


One of the valuable observations is that most of us would benefit by 
improving our sleep-schedule and ensuring we do sleep for sufficient 
time (probably longer than current habit).


--
Regards,
=dn

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


Re: Configuring an object via a dictionary

2024-03-17 Thread dn via Python-list

On 18/03/24 04:11, Peter J. Holzer via Python-list wrote:

On 2024-03-17 17:15:32 +1300, dn via Python-list wrote:

On 17/03/24 12:06, Peter J. Holzer via Python-list wrote:

On 2024-03-16 08:15:19 +, Barry via Python-list wrote:

On 15 Mar 2024, at 19:51, Thomas Passin via Python-list 
 wrote:
I've always like writing using the "or" form and have never gotten bit


I, on the other hand, had to fix a production problem that using “or” 
introducted.
I avoid this idiom because it fails on falsy values.


Perl has a // operator (pronounced "err"), which works like || (or),
except that it tests whether the left side is defined (not None in
Python terms) instead of truthy. This still isn't bulletproof but I've
found it very handy.



So, if starting from:

 def method( self, name=None, ):

  rather than:

 self.name = name if name else default_value

ie

 self.name = name if name is True else default_value


These two lines don't have the same meaning (for the reason you outlined
below). The second line is also not very useful.




the more precise:

 self.name = name if name is not None or default_value

or:

 self.name = default_value if name is None or name


Those are syntax errors. I think you meant to write "else" instead of
"or".

Yes, exactly. That's the semantic of Perl's // operator.

JavaScript has a ?? operator with similar semantics (slightly
complicated by the fact that JavaScript has two "nullish" values).



Thanks Peter!
(yes, sad consequences of suffering a neighbor's party-til-midnight 
followed by an 0530 meeting-start - children: don't code exhausted!)



Herewith, an illustration of how the corrected version of the above 
works - and how (in what seem unusual cases) it avoids any truthy/falsy 
confusion, as raised earlier in this thread:


>>> default_value = "default"
>>> name = "Fred Flintstone"
>>> name if name is not None else default_value
'Fred Flintstone'

>>> name = None
>>> name if name is not None else default_value
'default'
>>> name = False
>>> name if name is not None else default_value
False
>>> name = 1
>>> name if name is not None else default_value
1
>>> name = 0
>>> name if name is not None else default_value
0


Personally: I find the above coding more logical, because our primary 
interest is on 'the happy case', ie where the value has been assigned 
(to "name"); and the default_value is only applied as a "guard".



On the other hand, I dislike the not-condition because it forces me to 
think (and maybe dust-off DeMorgan). Accordingly:


>>> name = "Fred Flintstone"
>>> default_value if name is None else name
'Fred Flintstone'
>>> name = None
>>> default_value if name is None else name
'default'
>>> name = False
>>> default_value if name is None else name
False
...


YMMV!
NB your corporate Style Guide may prefer 'the happy path'...

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


Re: MTG: Introductions to PyQt and DataClasses

2024-03-17 Thread dn via Python-list

On 17/03/24 23:40, Jim Schwartz wrote:

Will it be recorded?


Better than that (assumption) "coming soon" - please join-up or keep an 
eye on PySprings' Meetup ANNs: https://www.meetup.com/pysprings/




On Mar 17, 2024, at 1:47 AM, dn via Python-list  wrote:

The Auckland Branch of NZPUG meets this Wednesday, 20 March at 1830 NZDT (0530 
UTC, midnight-ish Tue/Wed in American time-zones), for a virtual meeting.

Part 1: Learn the basics of PyQt with code examples.
Hannan Khan is currently consulting as a Data Scientist for the (US) National 
Oceanic and Atmospheric Administration. He holds a Bachelor's degree in 
Neuroscience as well as a Masters in Computer Science. As a keen member of the 
PySprings Users' Group (Colorado), his contribution is part of a collaboration 
between our two PUGs.

Part 2: Why use Dataclasses?
- will be the question asked, and answered, by yours truly. After surveying a 
number of groups, it seems most of us know that Dataclasses are available, but 
we don't use them - mostly because we haven't ascertained their place in our 
tool-box. By the end of this session you will, and will have good reason to use 
(or not) Dataclasses!

Everyone is welcome from every location and any time-zone. The NZPUG Code of 
Conduct applies. JetBrains have kindly donated a door-prize. Our BigBlueButton 
web-conferencing instance is best accessed using Chromium, Brave, Vivaldi, 
Safari, etc, (rather than Firefox - for now). A head-set will facilitate asking 
questions but text-chat will be available.

Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764049/
See you there!
=dn, Branch Leader
--
https://mail.python.org/mailman/listinfo/python-list




--
Regards,
=dn

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


MTG: Introductions to PyQt and DataClasses

2024-03-17 Thread dn via Python-list
The Auckland Branch of NZPUG meets this Wednesday, 20 March at 1830 NZDT 
(0530 UTC, midnight-ish Tue/Wed in American time-zones), for a virtual 
meeting.


Part 1: Learn the basics of PyQt with code examples.
Hannan Khan is currently consulting as a Data Scientist for the (US) 
National Oceanic and Atmospheric Administration. He holds a Bachelor's 
degree in Neuroscience as well as a Masters in Computer Science. As a 
keen member of the PySprings Users' Group (Colorado), his contribution 
is part of a collaboration between our two PUGs.


Part 2: Why use Dataclasses?
- will be the question asked, and answered, by yours truly. After 
surveying a number of groups, it seems most of us know that Dataclasses 
are available, but we don't use them - mostly because we haven't 
ascertained their place in our tool-box. By the end of this session you 
will, and will have good reason to use (or not) Dataclasses!


Everyone is welcome from every location and any time-zone. The NZPUG 
Code of Conduct applies. JetBrains have kindly donated a door-prize. Our 
BigBlueButton web-conferencing instance is best accessed using Chromium, 
Brave, Vivaldi, Safari, etc, (rather than Firefox - for now). A head-set 
will facilitate asking questions but text-chat will be available.


Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764049/
See you there!
=dn, Branch Leader
--
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-16 Thread dn via Python-list



On 17/03/24 12:06, Peter J. Holzer via Python-list wrote:

On 2024-03-16 08:15:19 +, Barry via Python-list wrote:

On 15 Mar 2024, at 19:51, Thomas Passin via Python-list 
 wrote:
I've always like writing using the "or" form and have never gotten bit


I, on the other hand, had to fix a production problem that using “or” 
introducted.
I avoid this idiom because it fails on falsy values.


Perl has a // operator (pronounced "err"), which works like || (or),
except that it tests whether the left side is defined (not None in
Python terms) instead of truthy. This still isn't bulletproof but I've
found it very handy.



So, if starting from:

def method( self, name=None, ):

 rather than:

self.name = name if name else default_value

ie

self.name = name if name is True else default_value


the more precise:

self.name = name if name is not None or default_value

or:

self.name = default_value if name is None or name

because "is" checks for identity, whereas "==" and True-thy encompass a 
range of possible alternate values?


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


Re: Configuring an object via a dictionary

2024-03-16 Thread dn via Python-list

On 16/03/24 21:15, Barry via Python-list wrote:




On 15 Mar 2024, at 19:51, Thomas Passin via Python-list 
 wrote:

I've always like writing using the "or" form and have never gotten bit


I, on the other hand, had to fix a production problem that using “or” 
introducted.
I avoid this idiom because it fails on falsy values.


As with any other facility, one has to understand ALL implications!

It must be one of those intensely-frustrating errors to track-down, 
which is then oh-so-simple to fix!


Are you able to list (real, if suitably anonymised) examples of where 
the truthy/falsy was inappropriate, please?


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


Re: Configuring an object via a dictionary

2024-03-15 Thread dn via Python-list

On 15/03/24 22:30, Loris Bennett via Python-list wrote:

Hi,

I am initialising an object via the following:

 def __init__(self, config):

 self.connection = None

 self.source_name = config['source_name']
 self.server_host = config['server_host']
 self.server_port = config['server_port']
 self.user_base = config['user_base']
 self.user_identifier = config['user_identifier']
 self.group_base = config['group_base']
 self.group_identifier = config['group_identifier']
 self.owner_base = config['owner_base']

However, some entries in the configuration might be missing.  What is
the best way of dealing with this?


How do you define "missing"?

Thus, @Thomas' suggestion may/not apply. It is neat and easy.

I usually plump for:

self.source_name = config[ "source_name" ] or default_value

but @Grant's warning applies!
(which is why the pythonic way is to use (and test for) None as a 
definition of "missing" (see also impacts of using default values and 
mutable data-structures)



LBYL cf EAFP:
When setting-up an environment like this, elements are often set to a 
default-value, and then user-settings, command-line arguments, and the 
like, applied in a priority-order sequence, amend as-appropriate. In 
this way, such problems will never arise.


This is the better course 90% of the time.


Which raises the next question:

What is the impact if some attribute is "missing"? ie if the 'whatever' 
must be identified by source_name (for example), then there is little 
point in assigning any values to the new class. Considerations which 
apply *after* this question, the __init__(), are at least 
equally-important considerations (see below)!




I could of course simply test each element of the dictionary before
trying to use.  I could also just write

self.config = config

but then addressing the elements will add more clutter to the code.


By which you mean that such "clutter" should only appear in the 
__init__() - which is not such a bad idea (but see below).


OTOH it is often helpful to one's comprehension to be given a prompt as 
to the source of the data. Thus, in later processing *config[ 
"source_name" ] may add a small amount of extra information to the 
reader, over self.source_name.


* maybe prepended "self.", or not...


Am assuming that passing all eight elements as individual arguments is 
off-the-table, embodying far too many 'negatives' (see below).




However, with a view to asking forgiveness rather than
permission, is there some simple way just to assign the dictionary
elements which do in fact exist to self-variables?


Assuming config is a dict:

self.__dict__.update( config )

will work, but attracts similar criticism - if not "clutter" then an 
unnecessary view (and understanding) of the workings of classes 
under-the-hood.



Another question:
When these values are used, are they all used at the same time, and 
never again? It may only be worth 'breaking-out' and making attributes 
from those which are used in multiple situations within the class's 
methods. If, the other extreme, they are only (effectively) passed from 
the __init__() to some sort of open() method, then pass the 
data-structure as an whole and delegate/remove the "clutter" to there. 
In that scenario, such detail would *only* has meaning *and* purpose in 
the open() method and thus no point in cluttering-up the __init__() with 
detail that is only required elsewhere!




Or should I be doing this completely differently?


YMMV, but I prefer the idea of transferring the environment/config as a 
whole (as above).


If it were a class (cf the supposed dict) then "clutter" is reduced by 
eschewing brackets and quotation-marks, eg "config.source_name".



If those eight-elements are not the entirety of that data-structure, 
then consider creating an interface-class, which is extracted (or built 
that way) from some wider 'environment', and used to set-up access to 
data-source(s) or whatever. Again, this aids understanding in knowing 
where data has been created/gathered, and improves confidence when 
utilising it down-the-line.


The other principle in only providing the required (eight) items of 
data, is that the 'receiving-class' needs no understanding of the 
structure or workings of the 'sending-class' = separation of concerns, 
and each class has single purpose/reason to change.



A variation on that might be to use a method/function as the interface:

access = Access( config.access_data )

Thus, the config class (instance) will need an access_data method to 
collate the data-items. The complimentary code in this Access.__init__( 
self, config, ) might be something like:


(
self.source_name,
self.server_host,
self.server_port,
self.user_base,
self.user_identifier,
self.group_base,

Re: A Single Instance of an Object?

2024-03-11 Thread dn via Python-list

Good question Rambius!

On 12/03/24 09:53, Ivan "Rambius" Ivanov via Python-list wrote:

Hello,

I am refactoring some code and I would like to get rid of a global
variable. Here is the outline:

import subprocess

CACHE = {}


First thought: don't reinvent-the-wheel, use lru_cache 
(https://docs.python.org/3/library/functools.html)




The global cache variable made unit testing of the lookup(key) method
clumsy, because I have to clean it after each unit test. I refactored
it as:

class Lookup:
 def __init__(self):
 self.cache = {}



Change "cache" to be a class-attribute (it is currently an instance.

Then, code AFTER the definition of Lookup can refer to Lookup.cache, 
regardless of instantiation, and code within Lookup can refer to 
self.cache as-is...



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


Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference

2024-03-06 Thread dn via Python-list

On 7/03/24 05:28, Jacob Kruger via Python-list wrote:
...
So, yes, know this comes across like some form of a scam/joke, or 
list-garbage, since it doesn't make any sense to me at all, but still 
just wondering if missing something, or should I shift over to 3.12 to 
see if if works differently, or just try reinstalling 3.11 from scratch, 
or should I retry the above in something like the VS code console, or a 
different python console, etc.?
Some of the facts, such as HOW the code was being executed were missing 
(see earlier request for a cut-down scenario, AND reports from others 
saying 'but it works for me').


The idea of importing a module into the REPL and then (repeatedly) 
manually entering the code to set-up and execute is unusual (surely type 
such into a script (once), and run that (repeatedly). As you say, most 
of us would be working from an IDE and hitting 'Run'. Am wondering why 
you weren't - but it's not important.


That said, the REPL is the perfect place to learn, experiment, and 
prototype - particularly when compared with the facilities of other 
language's eco-systems. The entirety of the on-line Tutorial cannot be 
wrong! (although, after a quick review, I've failed to see where the 
Tutorial mentions the usual development mode, apart from two very brief 
asides (the most useful is almost at the very end(?)) - but then (as 
they say) the objective is to show the language!


The lesson-learned is that there are different 'environments' and 
different ways of building the environment in which the code will run. 
That's a valuable lesson, and full of subtlety!


Glad to see that comparing id()s was useful - for diagnosis but not 
solution. Other tools might include the locals() and globals() 
functions. You may also have detected that many of us try to avoid 
globals and the implicit assumptions about the behavior of mutable 
collections (eg lists) when treated as 'global'. Then there are 
"closures", the "LEGB" rule, namespaces, scope, and ...


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


Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference

2024-03-05 Thread dn via Python-list

Jacob,

Please reduce the problem to a small code-set which reproduces the 
problem. If we can reproduce same, then that tells us something. At the 
very least, we can experiment without having to expend amounts of time 
in a (likely faulty) bid to reproduce the same environment.


Also, code is the ultimate description!


Perhaps start with a small experiment:

- after l_servers is created, print its id()
- after the global statement, print its id()
- after the clear/reassignment, print its id()

Is Python always working with the same list?
Please advise...


On 6/03/24 07:13, Jacob Kruger via Python-list wrote:

Hi there


Working with python 3.11, and, issue that confused me for a little 
while, trying to figure out what was occurring - unless am completely 
confused, or missing something - was that, for example, when having 
pre-defined a variable, and then included it in the global statement 
inside a function, that function was still referring to a completely 
local instance, without manipulating outside variable object at all 
unless I first executed a form of referral to it, before then possibly 
assigning a new value to it.



Now, this does not seem to occur consistently if, for example, I just 
run bare-bones test code inside the python interpreter, but consistently 
occurs inside my actual testing script.



Basically, in a file with python code in that am using for a form of
testing at the moment, at the top of the file, under all the import
statements, I initiate the existence of a list variable to make use of

later:


# code snippet

l_servers = []

# end of first code snippet


Then, lower down, inside a couple of different functions, the first line
inside the functions includes the following:
# code snippet
     global l_servers
# end code snippet

That should, in theory, mean that if I assign a value to that variable
inside one of the functions, it should reflect globally?

However, it seems like that, while inside those functions, it can be
assigned a new list of values, but if I then return to the scope outside

the functions, it has reverted back to being an empty list = []?


The issue seems to specifically (or not) occur when I make a call to one 
function, and, in the steps it's executing in one context, while it's 
not doing anything to the list directly, it's then making a call to the 
second function, which is then meant to repopulate the list with a brand 
new set of values.



Now, what almost seems to be occurring, is that while just manipulating 
the contents of a referenced variable is fine in this context, the 
moment I try to reassign it, that's where the issue is occurring .



Here are relevant excerpts from the file:-


# start code

# original assignation in main part of file

l_servers = []


# function wich is initially being executed

def interact():
     global l_servers
     # extra code inbetween choosing what to carry out

     # ...

     # end of other code

     bl_response, o_out = list_servers()

     if bl_response: # just make sure other function call was successful

     l_servers.clear() # first make reference to global variable

     for srv in o_out: l_servers.append(srv) # now re-populate items

     # end code snippet from inside interact function

# end of interact function

# end of code snippet


That other function being called from within, list_servers() was 
initially just trying to populate the values inside the global list 
variable itself, but was ending up in a similar fashion - reverting to 
initial empty value, but, the above now seems to work, as long as I 
first make reference to/manipulate/work with global variable instead of 
just trying to reassign it a brand new value/set of items?



So, am I missing something obvious, have I forgotten about something 
else - yes, know that if was working from within an embedded function, I 
might need/want to then use the nonlocal statement against that variable 
name, but, honestly, just not sure how this can be occurring, and, it's 
not just with this one list variable, etc.?



If I try simple test code from within the python interpreter, using 
different types of variables, this does also not seem to be the same all 
the time, but, don't think it can relate to an iterable like a list, or 
else, just in case, here is the code snippet with all the import 
statements from the top of that file, in case something could be 
overriding standard behaviour - not likely in this context, but, really 
not sure what's occurring:


# import code snippet

import requests, time
from requests.auth import HTTPBasicAuth
import psutil as psu
import pytz
import bcrypt
from copy import copy
from datetime import datetime, timedelta, timezone
from dateutil.parser import parse

# end of import snippet


Thanks if you have any ideas/thoughts on the matter


Jacob Kruger
+2782 413 4791
"Resistance is futile!...Acceptance is versatile..."




--
Regards,
=dn
--

Re: Can one output something other than 'nan' for not a number values?

2024-02-19 Thread dn via Python-list

On 20/02/24 01:04, Chris Green via Python-list wrote:

dn  wrote:

On 18/02/24 09:53, Grant Edwards via Python-list wrote:

On 2024-02-17, Cameron Simpson via Python-list  wrote:

On 16Feb2024 22:12, Chris Green  wrote:

I'm looking for a simple way to make NaN values output as something
like '-' or even just a space instead of the string 'nan'.
[...]

 Battery Voltages and Currents
 Leisure Battery - 12.42 volts  -0.52 Amps
 Starter Battery -   nan voltsnan Amps

What I would like is for those 'nan' strings to be just a '-' or
something similar.



The simplest thing is probably just a function writing it how you want
it:

   def float_s(f):
   if isnan(f):
   return "-"
   return str(f)

and then use eg:

   print(f'value is {float_s(value)}')

or whatever fits your code.


Except he's obviously using some sort of formatting to control the
number of columns and decimal places, so 'str(f)' is not going to cut
it. Is the basic floating point number formatting functionality seen
when using f-strings or '%' operator part of the float type or is it
part of the f-string and % operator?


It's part of the PSL's string library: "Format Specification
Mini-Language"
https://docs.python.org/3/library/string.html#format-specification-mini-language

Has the OP stated if we're talking 'Python' or numpy, pandas, ...?


Just python, on a Raspberry Pi, so currently Python 3.9.2.


Concur with earlier advice (and assuming is only a consideration during 
output) - use if.


Alternately, encode appropriately during the data-capture phase.


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


Re: Can one output something other than 'nan' for not a number values?

2024-02-19 Thread dn via Python-list

On 20/02/24 05:58, Grant Edwards via Python-list wrote:

Here's a demonstration of how to hook custom code into the f-string
formatting engine. It's brilliantly depraved.

https://stackoverflow.com/questions/55876683/hook-into-the-builtin-python-f-string-format-machinery

 From the above:

 You can, but only if you write evil code that probably should
 never end up in production software. So let's get started!
 
 I'm not going to integrate it into your library, but I will show

 you how to hook into the behavior of f-strings. This is roughly
 how it'll work:
 
  1. Write a function that manipulates the bytecode instructions of

 code objects to replace FORMAT_VALUE instructions with calls
 to a hook function;
 
  2. Customize the import mechanism to make sure that the bytecode

 of every module and package (except standard library modules
 and site-packages) is modified with that function.

Final code is here:

https://github.com/mivdnber/formathack


Some of this (Expression components inside f-strings) newly available in 
v3.12 (PEP-701) - which can be used in production...


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


Re: Testing (sorry)

2024-02-18 Thread dn via Python-list

On 19/02/24 12:09, Grant Edwards via Python-list wrote:
...


But posts to the list still seemed to vanish into the ether while
emails from both accounts reached other destinations without delay,

During this process a number of posts from other users did appear in
the list archive and at at _one_ of the two e-mail addresses which I
had subscribed.

But no sign of any of my posts.

About 24 hours later, all of my posts (and the confirmation e-mails)
all showed up in a burst at the same time on two different unrelated
e-mail accounts.

I still have no clue what was going on...


Looking at the email-headers, there are sometimes considerable delays 
between messages submitted to the List-reflector, and their outward 
transmission (to me).


Interestingly, there's something strange about the queuing. Instead of 
FIFO it seems some messages arrive ahead of others, ie out-of-sequence.

(wonder if explained by submission via email or Usenet?)

I've noted long delays too. Perhaps (also) to do with time-of-day?

Always feel slightly embarrassed if 'repeat' an answer* that someone 
else had previously submitted, eg __new__ thread and @MRAB. However, if 
the reflector 'holds onto' the earlier message, then how should I/anyone 
know?


* yes, repetition improves learning, slightly different words may help 
comprehension; but doubt I can express anything better than the 
aforementioned does/did/can.


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


Re: Can one output something other than 'nan' for not a number values?

2024-02-18 Thread dn via Python-list

On 18/02/24 09:53, Grant Edwards via Python-list wrote:

On 2024-02-17, Cameron Simpson via Python-list  wrote:

On 16Feb2024 22:12, Chris Green  wrote:

I'm looking for a simple way to make NaN values output as something
like '-' or even just a space instead of the string 'nan'.
[...]

Battery Voltages and Currents
Leisure Battery - 12.42 volts  -0.52 Amps
Starter Battery -   nan voltsnan Amps

What I would like is for those 'nan' strings to be just a '-' or
something similar.



The simplest thing is probably just a function writing it how you want
it:

  def float_s(f):
  if isnan(f):
  return "-"
  return str(f)

and then use eg:

  print(f'value is {float_s(value)}')

or whatever fits your code.


Except he's obviously using some sort of formatting to control the
number of columns and decimal places, so 'str(f)' is not going to cut
it. Is the basic floating point number formatting functionality seen
when using f-strings or '%' operator part of the float type or is it
part of the f-string and % operator?


It's part of the PSL's string library: "Format Specification 
Mini-Language" 
https://docs.python.org/3/library/string.html#format-specification-mini-language


Has the OP stated if we're talking 'Python' or numpy, pandas, ...?

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


Re: Using __new__

2024-02-17 Thread dn via Python-list

On 18/02/24 13:21, Jonathan Gossage wrote:
The problem is that if you are dealing with a library class, you may 
have times when the superclass is 'object' while at other times, with a 
different inheritance hierarchy, the superclass may need arguments. My 
thought is that the object class __new__ method should not choke on 
arguments, just ignore them.


All true.

So, what you're looking for is one mechanism to rule them all?

Not going to happen: for exactly the reasons you've stated. If you 
really want to get right 'down into the weeds' with a __new__() 
constructor, then you're well into customisation-territory.


I think it would be 'going nuts' but...
If it 'absolutely, positively, ...' then perhaps introspect the 
super-class and modify the call based-upon whether it is 'something' or 
"object"?
(in similar fashion to the singleton's if-statement attempting to make 
sure it is unique)


- perhaps someone knows a better/proper way to do this?

Suggested research: custom classes, ABCs, and meta-classes...

See also recent improvements to Python which have made it easier for 
sub-classes (and Descriptors - __set_name__() ) to identify 
who/how/where to 'phone home', in case (also) applicable...



When I talk about 'object', I am talking about the ultimate base class 
of any inheritance hierarchy.  have seen the class named 'object' called 
that.


Correct.

The earlier comment was that

class S( object ):

is 'tradition', and synonymous with:

class S:

(not disputing the concept of "object" as the base class)


Not correct.

Please see last paragraph from previous message:


On Sat, Feb 17, 2024 at 7:06 PM dn via Python-list 
mailto:python-list@python.org>> wrote:

...


PS please reply to the list - there may be others who can learn
from, or
contribute to, this conversation!

...

--
Regards,
=dn

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


Re: Using __new__

2024-02-17 Thread dn via Python-list

On 18/02/24 12:48, Jonathan Gossage wrote:
The problem that I am facing is that when the superclass is not 
'object', the __init__ method may well need arguments. I do not know how 
to determine if the superclass is 'object'. For what it is worth, any 
attempt to use this with different arguments should return the initial 
singleton and ignore further attempts to create a second instance.

1 "object"
don't understand. Perhaps give us a broader description of the problem? 
Remember also ABCs (Abstract Base Classes).


2 arguments
yes, must accommodate arguments in __new__() if some/same are needed in 
__init__() However, when using the default "object", the super() does 
not need, use, or want, any arguments to be passed.


3 singleton
don't think that is happening!


PS please reply to the list - there may be others who can learn from, or 
contribute to, this conversation!


--
Regards,
=dn

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


Re: Using __new__

2024-02-17 Thread dn via Python-list

On 18/02/24 11:35, Jonathan Gossage via Python-list wrote:

I am attempting to use the __new__ method in the following code:
class SingletonExample(object):

 _instance = None

 def __new__(cls, **kwargs):
 if cls._instance is None:
 cls._instance = super().__new__(cls, **kwargs)
 return cls._instance

 def __init__(self, **kwargs) -> None:
 our_attributes = ('h', 'x')
 if kwargs is not None:
 for k, v in kwargs.items():
 if k in our_attributes:
 setattr(self, k, v)

a = SingletonExample(h=1)

and I get the following result:

(PRV) jonathan@jfgdev:/PR$ python -m Library.Testing.test2
Traceback (most recent call last):
   File "", line 198, in _run_module_as_main
   File "", line 88, in _run_code
   File "/mnt/ProgrammingRenaissance/Library/Testing/test2.py", line 16, in

 a = SingletonExample(h=1)
 ^
   File "/mnt/ProgrammingRenaissance/Library/Testing/test2.py", line 6, in
__new__
 cls._instance = super().__new__(cls, **kwargs)
 ^^
TypeError: object.__new__() takes exactly one argument (the type to
instantiate)

I am quite puzzled as it looks as if this code will not work if the
super-class is 'object'. Any suggestions on how to proceed?


Don't be puzzled. Read the error-message.

Change the super-call to: cls._instance = super().__new__(cls)
and happiness will follow...


That said, mystifications - not sure if this meets the/your definition* 
of "singleton", because:


- it can be aliased, eg
a = SingletonExample(h=1)
b = SingletonExample(x=2)

- when it is, the effect is an accumulation of attributes and values
a = SingletonExample(h=1)
b = SingletonExample(h=2)
print( a.__dict__, b.__dict__, )

- it can be re-created with a different value, eg
a = SingletonExample(h=1)
a = SingletonExample(h=2)

- and can be 'regenerated':
a = SingletonExample(h=1)
a = SingletonExample(x=2)

- all failures are silent


* noting "Nowadays, the Singleton pattern has become so popular that 
people may call something a singleton even if it solves just one of the 
listed problems." (https://refactoring.guru/design-patterns/singleton)



YMMV!

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


Re: test-ignore

2024-02-15 Thread dn via Python-list

On 16/02/24 13:29, Skip Montanaro via Python-list wrote:



Test post to see if my Newsgroup post program is working.


Aim your test messages at alt.test, please.



I agree that basic Usenet connectivity messages should go to alt.test. It's
not clear from the original post, but if the poster's aim was to see if
posts to comp.lang.python traverse the gateway and show up on this list,
then alt.test won't help.


Coincidentally (I hope), today have received a couple of poorly-executed 
spam/phishing messages purporting to be from this list or "Tutor".


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


Re: Extract lines from file, add to new files

2024-02-04 Thread dn via Python-list

On 4/02/24 13:20, avi.e.gr...@gmail.com wrote:

Dave,

You and I have had some experience in teaching or tutoring others and I think 
it fair to say our motivation is closer to teaching someone how they can fish 
for themselves rather than just handing them a fully-cooked fish.


Which may push the debate 'up' a level, in that there are two pertinent 
Python Discussion Lists (amongst the many): Tutor which is expressly for 
learners (and tutors), and this one which is to discuss Python. 
Accordingly, one might suggest that people 'here' are looking for a 
direct answer - the fish (having tried to fish for themselves), but 
learners (seeking to learn to fish) should be asking elsewhere.


This would sort-out the type/level of questions that OPs may have. As 
well as indicating an appropriate approach to 'answers'.


However, there's no rule which says one has to ask in one place or the 
other (nor am I suggesting such, although...). Then again, might the 
lack of forethought evident in some questions and the forum-used, 
indicate a type of person who wouldn't investigate to see which is the 
best place for his/her enquiries anyway?


Tutor List: https://mail.python.org/mailman/listinfo/tutor
Lists Overview: https://mail.python.org/mailman/listinfo



My favorite kinds of questions, thus, include someone who explains what they 
are trying to do and shows some code along with indications of what it produced 
(including error messages) and what it should produce. Then the question should 
not be a request to just FIX THIS or WRITE IT FOR ME but asking if someone can 
show what they did wrong with some idea where it went wrong.

This may not be so common but it allows faster and easier help.


+1


...


I will end with a comment. I have heard of interview techniques for a job where 
they deliberately supply a problem in which the goal is not so much to be easy 
to solve in front of them in real time but to watch how the person looking for 
a job responds to the uncertainties and asks follow-up questions or verbalizes 
things like, if it is like this, I might use this technique but if you also 
need that then ...

So, I shudder to think what happens if someone being interviewed turns around 
and asks us and further confuses things with changes to make it harder to 
recognize they are asking for outside help. The answer expected may well be to 
NOT use say the older versions of PASCAL to do something but switch to 
something better suited (and for that matter available.)  I would not want to 
program the DES encryption/decryption method in Pascal again! And these days, 
it seems much better to just find a module or package that meets such needs.


As you know, I investigate Cognitive Psychology. Accordingly, such is 
interesting to me. In many cases, I'll interview for motivation, not 
just particular skills - but perhaps that's another can-of-worms.


How about "when is 1 + 1 not 2?". This is a bit of a mind-bender, but 
leads towards debugging ability* - what if your code was showing some 
unbelievable result like this?


The answer is (or rather, "could be") 10, ie we're looking at binary cf 
decimal, coding.


Do I hear some groans? Yes, fair-enough! There was absolutely no 
"context" to the question - whereas when coding/debugging we would 
expect to have some 'framing' of our thinking. At the same time, 'fixed 
mode thinking' will prevent many people from even considering such 
possibilities - whether as-asked or in a dev.env...



* In the ?good old days, career progression was thought to be: 
(mainframe) Computer Operator, to Computer Programmer, to Systems 
Analyst, etc. However, as I pointed-out (to an IBM 'big-wig' who took an 
instant dislike as a result) the valued skills of an Analyst are that 
(s)he can see 'patterns' - whereas the skills of debugging involve 
realising why an expected pattern doesn't work (as-expected).



Another analysis might be to decide if the job requires a 'lateral 
thinker' or a more single-minded approach. (us lateral thinkers tend to 
ask (loads of) questions, and thus can be quite 'annoying' individuals).


Then there is the main-stay of many job-adverts: "attention to detail" 
and the question of whether someone who can't [be bothered to] write an 
half-decent email-message (with spell-checker likely built-in) is going 
to be productive when communicating with a pedantic compiler?



Again, some people are suited to this business (or specific jobs 
within), and some (?many) are not - but many are (perhaps reluctantly) 
programming to get some other job done...


--
Regards,
=dn

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


Re: Extract lines from file, add to new files

2024-02-03 Thread dn via Python-list
Every trainer, in any field, has to deal with these problems - all the 
time, and over-and-over.



On 4/02/24 06:58, Thomas Passin via Python-list wrote:
In my view this whole thread became murky and complicated because the OP 
did not write down the requirements for the program.  Requirements are 
needed to communicate with other people.  An individual may not need to 
actually write down the requirements - depending on their complexity - 
but they always exist even if only vaguely in a person's mind.  The 
requirements may include what tools or languages the person wants to use 
and why.


If you are asking for help, you need to communicate the requirements to 
the people you are asking for help from.


The OP may have thought the original post(s) contained enough of the 
requirements but as we know by now, they didn't.


There is another possible interpretation in such situations (not 
necessarily this one): that the person is fixated on a particular 
solution (and unable/unwilling to adjust his/her thinking to consider 
more widely).


Thus, the question is not: 'here's an entire problem, how can it be 
solved', but more: 'I have a solution, and want help to implement it 
(and only it) just-so'.



The latter is an interesting psychology:

1
an experienced person who is trying to translate from one tool to 
another (Python), but discovers that a word-for-word solution is 
difficult because of the artificial-constraints they've placed on the 
situation.


2
a beginner who doesn't know what (s)he doesn't know and comes-up with an 
idea, but fails to appreciate that there is likely more than one path to 
the goal.



The person asking for help may not realize they don't know enough to 
write down all the requirements; an effort to do so may bring that lack 
to visibility.


In the case of 'Beginners' this should probably be taken-as-read!

Which is why we will always find ourselves asking questions or 'please 
give more information'...



However, there are other reasons, eg corporate concerns or personality; 
why people don't want to give more information. The former is reasonable 
(have suffered from same myself). The latter may reveal that the person 
is 'difficult to deal with'...



Mailing lists like these have a drawback that it's hard to impossible 
for someone not involved in a thread to learn anything general from it. 
We can write over and over again to please state clearly what you want 
to do and where the sticking points are, but newcomers post new 
questions without ever reading these pleas.  Then good-hearted people 
who want to be helpful end up spending a lot of time trying to guess 
what is actually being asked for, and maybe never find out with enough 
clarity.  Others take a guess and then spend time working up a solution 
that may or may not be on target.


So please! before posting a request for help, write down the 
requirements as best you can figure them out, and then make sure that 
they are expressed such that the readers can understand.


Unfortunately, if the person doesn't understand the problem (leave-aside 
any ideas of solution), then (s)he will not be able to clearly 
communicate same to us, in any way, shape, or form...


Which brings one to the question: if a person cannot express the problem 
clearly and completely, is (s)he suited to development work? If the 
problem is not understood, could 'the solution' ever be more than an 
exercise in hope?

(prototyping and experimentation aside)


Yes, it is frustrating to invest time and effort in helping someone, 
only for same to disappear 'into a black hole'. The lack of response 
seems to indicate a lack of respect or appreciation. Is this perhaps 
part of today's "consumer" life-style, where so few are contributors or 
creators?



On the other side of that coin: do the people who make assumptions and 
(kindly) blaze-ahead with 'a solution', actually help the conversation? 
If the assumptions are correct, yes! What if they are not?



...and don't get me started on folk who want us to do their 
training-assignments or build some application, for them!



As a slight aside: on one training-course DiscussionList/BulletinBoard 
set-up, if a trainee asked a question without a descriptive 
title/SubjectLine, eg "Python not working" or "Urgent: please help"; I 
asked them to re-post with a title that would help others in a similar 
situation find the topic - and closed the original thread.


Some found it "brutal" - probably skewing towards those who felt 
"Urgent" because they'd left things too close to deadline. Others joined 
the (later) thread because they could identify the topic and realise 
their interest in learning or contributing to the conversation...



Time pressures lead to a multitude of evils!


There's a quotation that goes something like "the poor will be with your 
always"?

(?possibly Biblical)

Whether we (here) are talking about 'poor' manners, 'poor' 
understanding, 'poor' communication skills, 'poor' 

MTG: pytest (NZPUG, Auckland, VacExcHndlrs)

2024-01-31 Thread dn via Python-list
Wed 7 Feb (evening NZDT) will be the last virtual gathering in the 
current Vacation Exception Handlers (VacExcHndlrs) series 
(https://danceswithmice.info/Python/2024/VacExcHndlrs.html).


You are cordially-invited to join us to investigate the pytest Python 
testing framework.


"The pytest framework makes it easy to write small, readable tests, and 
can scale to support complex functional testing for applications and 
libraries."



Pre-requisites:

1 Head-set to ask questions and make contributions
2 Lab-/Log-/Note-book
3 Python 3.8+ installed
4 Ability to write intro-level Python program[me]s (at least)
5 Credentials to install from PyPi ("The Cheese Shop")
6 Preparedness to research, experiment, work with others...
As before, we will follow a café style of meeting. So, come prepared 
with a list of objectives you would like to achieve and a list of 
achievements you will be ready to share.



Possible (but far too many) topics:

- installing pytest (individual, system-wide, PyCharm, VSCodium, ...)
- TDD's (Test-Driven Development) red-green refactoring
- the Python assert-statement
- the project directory-tree and auto-discovery
- adding simple-tests
- running pytest
- reporting
- structuring the code-base to facilitate testing
- advantages/disadvantages of automated testing
- using a GAI to suggest/generate tests
- fixtures and dependencies (set-up and/or tear-down)
- scopes (function, class, module, session)
- parametrizing
- monkey-patching
- CI/CD chaining you've built
- plug-ins you're finding helpful
- coverage
- testing strategies
- other testing frameworks and aids
(open-ended - what would you like to add?)


Come to participate, learn-from, and help others!
Please RSVP at https://www.meetup.com/nzpug-auckland/events/298901851/


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


Re: Extract lines from file, add to new files

2024-01-29 Thread dn via Python-list

On 30/01/24 05:15, Rich Shepard via Python-list wrote:

On Fri, 12 Jan 2024, Rich Shepard via Python-list wrote:


For my use 1) the salutation and email address (always with an '@') are
sequential and 2) I'm developing the script to extract both from the same
file.


I've looked at my Python books "Python Crash Course," "Effective Python,"
and "Python Tricks The Book" as well as web pages in my searches without
finding the answer to what may be a simple question: how to specify a
variable in one file that has its values in another file.

Specifically, how to I designate the salutation holder in the message file
and pass it the name value from the name/email address file?

If this explanation is not sufficiently clear I'll re-write it. :-)



It seems clear - but maybe we (all) misunderstand?

The books don't cover it - but is there a reason why they don't?


(Thunderbird did not thread this message with earlier ones, and it seems 
some time has passed/memory is fading - but hopefully have remembered 
content)



As said previously, the idea of two physical-files containing 
logically-related data (without any form of cross-reference between) is 
bad design.


In the current file, there is one physical structure and each person's 
details are logically-related by proximity. A long way from ideal, but 
workable (as you've described).


However, once split into two files, there is no way to guarantee that 
the two logically-related data-items (name and address) will continue to 
be related by their physical position in the respective files. Worse: 
whilst it would seem apparent that "Alice" from the names file might be 
related to the address "al...@domain.tld", how could one know if "Bob" 
actually corresponds to "list-mem...@domain.tld"?


This is why dicts, databases, etc, offer keys (as labels for 
data-items/dependent components)!



After a quick look at Eric's Crash Course, yes, his files-intro example 
(digits of pi) is unlikely to have any practical reality (and I work 
with statisticians and quants!). However, at the end of that chapter 
(10), there is mention of JSON files. A JSON version of the existing 
single-file structure will provide human-readable labeling of 
data-items, give better separation between individuals' data, and show 
how name and address are linked. Recommend solving 'the problem' that 
way! (as previously discussed by others 'here', IIRC)


Slatkin's Effective Python doesn't seem to discuss the basics of files 
at all (presumes such knowledge of the reader). It dives into important, 
but rather technical discussions, comparing strings and bytes - somewhat 
beyond the complexity-level of this discussion. That book does however 
include discussions such as "Prefer Multiple Assignment Unpacking over 
Indexing" (Item 6 - also points to Item 19) where relative-positioning 
(indexing in other words) is advised-against.



If you wish to persist with this two-file structure, please see earlier 
responses (again, IIRC) and discussion of file-merge operations. As 
these date back to mainframes and the days of storing files on mag-tape, 
I'd be surprised to see them discussed in 'modern' texts. However, the 
principle is: read a record from each file, do-the-business, read the 
next 'pair' of physically-related records, rinse-and-repeat.


If you require further assistance: how about showing a couple of 
relevant lines of the data-file(s) and the pertinent parts of the code, 
along with a description of what's going-wrong or not making sense to you?


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


Re: Extract lines from file, add to new files

2024-01-15 Thread dn via Python-list

On 15/01/24 21:13, Greg Ewing via Python-list wrote:

On 15/01/24 1:54 pm, dn wrote:

Soon after, Wirth simplified rather than expanded, and developed Pascal.


Before Pascal there was Algol-W, which Wirth invented as a rebellion
against how complicated Algol 68 was becoming.

When I first saw this I was stunned, then attracted to its simplicity, 
but then steered-away once realised that it needed 'more' to cope with 
'the outside world'.


Pascal was intended as a teaching language, and as such it was lacking
in practicality in a few spots. But it didn't need much tweaking to
make it a very useful language. UCSD Pascal, Turbo Pascal, Delphi, etc.
enjoyed a lot of popularity. A variant of UCSD was the main language
for Macintosh application development for a number of years.



Ironically, I didn't come across Pascal as a teaching-language.

Borland were trying to turn Turbo Pascal into a practical development 
environment, beyond teaching (as with others of their 'Turbo' series). 
As I say, it didn't float my business-world boat.
- not before I won a case a wine from Philippe Kahn's own vineyard for 
solving some 'interview question' and exchanging jokes with him, in 
French, at some Trade Show in London. Two surprises: one, that it 
actually turned-up a few weeks later, and two, that I (suddenly) had so 
many friends!


Ah, the good, old days...


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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 14:45, Chris Angelico wrote:

On Mon, 15 Jan 2024 at 12:42, dn via Python-list  wrote:


On 15/01/24 14:33, Chris Angelico via Python-list wrote:

On Mon, 15 Jan 2024 at 12:12, dn via Python-list  wrote:

Here's another witticism I'll often toss at trainees (in many languages,
and especially in UX): just because we can do it, doesn't make it a good
idea!



Programming. We were so busy with whether we COULD that we didn't stop
to think if we SHOULD.

I think that's basically my whole life.


Don't be too hard on yourself.

My life-advice has always been "don't do anything I wouldn't do"
- which pretty-much gives you carte blanche.



I would NEVER give that advice to anyone. They would leave the dishes
unwashed, and a number of other problems :)


I'd soon have you sorted-out - except for one small problem: all the 
dishes have been done!


If you can get here before the rain, the lawn needs mowing...

--
Regards,
=dn

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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 14:33, Chris Angelico via Python-list wrote:

On Mon, 15 Jan 2024 at 12:12, dn via Python-list  wrote:

Here's another witticism I'll often toss at trainees (in many languages,
and especially in UX): just because we can do it, doesn't make it a good
idea!



Programming. We were so busy with whether we COULD that we didn't stop
to think if we SHOULD.

I think that's basically my whole life.


Don't be too hard on yourself.

My life-advice has always been "don't do anything I wouldn't do"
- which pretty-much gives you carte blanche.

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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 11:47, Chris Angelico via Python-list wrote:

On Mon, 15 Jan 2024 at 09:40, dn via Python-list  wrote:

The basic challenge came from my earlier (and blasé) repetition of the
Python refrain "everything in Python is an object". Which led to:

...


So, no, there's an "everything" which (might be) an object but which
cannot be used in that scenario.


More accurately, every VALUE in Python is an object. This does not
mean that syntax is an object. Very few languages would say that every
single grammatical element is a value.


+1

Thank you. This old-dog will try to re-learn that term...



Yes, it's sloppy to say "everything" is an object, but it's also
rather nonintuitive to claim that, therefore, syntax elements are all
objects. It's like claiming that everything that this dealership sells
is a car (or "everything in this dealership is a car"), and therefore
the dealership's name must itself be a car.


To say nothing of 'extended warranties'!
(and their dubious rationale)



That said, does anyone think that something like:

  for a_function( etc ) in iterable/iterator:

is acceptable?
- see both Python definition and (full-)quotation.

I've not come-across a language which does allow such - YMMV/mea culpa;
and am struggling to see how it could possibly be useful.


You could do something close to that:

for a_function(etc)[0] in iterable: ...

because an assignment target can contain an arbitrary expression
followed by the subscript.


Here's another witticism I'll often toss at trainees (in many languages, 
and especially in UX): just because we can do it, doesn't make it a good 
idea!




* Looking at the correspondent's email-address (cf 'handle') - and as an
unfair stereotype, raises the question of issues related to (English)
language-skills - which, arrogantly implies/assumes that native
English-speakers are all highly-capable. (?) A negative-interpretation
is to note his apparent intelligence, but wonder if failing to represent
others' comments fairly is deliberate, or carelessness. Is there an
irony in behaving/failing in such, whilst attempting to hold Python's
structure to some golden-ideal?


Seems likely.



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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 08:06, AVI GROSS via Python-list wrote:
...> You provided a way to create an anonymous function and that was not 
enough.

I wonder if you could throw in the new := walrus operator to similarly make
a named lambda function in a similar way.


Why would @Chris have anything to do with the 'walrus-operator'?

PS our interlocutor doesn't like colloquialisms such as these - despite 
them being near-and-dear to our hearts!


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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 01:28, Left Right wrote:

Second time to ameliorate wording-dispute in this thread! The original
phrase was: "[modified] BNF". Some of us have worked with various forms
and evolutions of BNF since back in the days of COBOL-60 proposals, and
know it when we see it!


OK, here are the conceptual differences between what Python grammar
language does and what you'd expect from anything that's based on BNF,
modified or not:

Python isn't a context-free language, so the grammar that is used to
describe it doesn't actually describe the language... so, it's a
"pretend grammar" that ignores indentation.  BNF is supposed to be
used to describe the language, it's not a "pretend" or "pseudo"
grammar, in a way we have at least two established grammar for
pseudo-code.

BNF and derivatives don't have an inherent mechanism for tiebreaks.
The mechanism is necessary because BNF rules can be tried in any
order.  Some grammar languages derived from BNF declare ambiguous
grammars invalid, some allow ambiguity, but say that the longest
prefix wins, and if there's still ambiguity after that, then such
grammar is invalid, some have special constructs to define "priority"
etc. My reading of Python grammar is that it works like PEG, where
rules are tried in the order they are defined.  This makes it less
expressive, but easier to work with.  This is, probably, the most
fundamental difference between the BNF family and the PEG family.

BNF and family languages rarely incorporate elements of Perl-like
regular expression parsing in the language (i.e. things like
lookaheads, lookbehinds etc.) This is more typical of the PEG family.

On top of this, the Python grammar language has a bunch of
"inventions" that are unique to it (I've never seen any other grammar
language use '.' in the same way Python uses it).  So, there's that
too.

Having worked with a bunch of different grammar languages, the one
used for Python isn't a recognizable BNF derivative.  I think the
authors used this as a description in the same way as today a lot of
programmers would use the word "IDE" to describe any text editor or
"REST" to describe any kind of server-client protocol over HTTP and so
on.  Or, how we'd use "Xerox" to name a copier machine, even if that
company didn't manufacture it, and even if the tech used for copying
is completely different.  And that's why I wrote that the grammar is
actually more like PEG, adding that it's neither, but seems to fall
more into that later category.


We are in broad-agreement. I'd enjoy the discussion, except that I can't 
see where it is leading or how it will benefit you...


Where we seem to differ is the length of time we've been part of the 
Python-world.


An important point is that languages are often described as 'living', 
because they evolve over time. I'm relieved to note that the youngsters 
in the family have stopped describing 'everything' as "awesome". That 
word, has taken-on aspects of the original meanings of "awful". The 
former being positive-factors, and the negative ascribed to the latter. 
However, we don't have to step far back into history to find that 
"awful" meant 'full of awe' or awe-inspiring - with no connotation of 
'good' or 'bad'. There was no need for a word with opposite-meaning, 
apart from "mundane".


Similarly, spoken-language often lacks precision. My CO, to this day, 
uses phrases like "all done" [with time for me to take a breath, 
followed by "except ...", eg "are we ready to leave for ...?". This 
drives me nuts. (the word "nuts" requires consideration too!) Thus, have 
learned to elicit the pertinent information with phrasing such as "what 
is left to be done?" rather than arguing the illogic between "all" and 
"except".


Python is not different. We're currently looking at version 3.12, which 
implies three major iterations of the language. Accordingly, when it was 
a 'green fields project', what may have been a pure and elegant 
expression of a language, has become "acquisitive". Sometimes these 
additions-and-alterations have required compromise, eg lack of elegance. 
Sometimes, it has been realised that there is a flaw, and things need to 
be improved, even removed.


You've made comments about BNF. Like Python, it is a 'language' (a bit 
of stretch, but...) which has also been pulled, poked, and perhaps 
contorted over time. It had a body of folk who understood its 
expression, and therefore it made sense to stick with some variation of 
it (even warts-and-all) rather than going with something 'new'.



All of which creates the sorts of issues described.

The PEG-parser is a comparatively-recent improvement - other aspects 
previously-mentioned.


I'm not going to touch "Perl".

Is there really some sort of standard-understanding/format for 
"pseudo-code"? (ISO?)


Yes, there's some 'pretense' (not sure I'd choose that exact term). 
However, it is working for the vast-majority. Perhaps after using Python 
for so long, I'm comfortable accepting such 

Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 15/01/24 10:23, Chris Angelico via Python-list wrote:

On Mon, 15 Jan 2024 at 08:15, Left Right  wrote:

Python grammar rules prevent function definition from
appearing in left-hand side of the head of the for loop.  However, a
variable declaration, which is also a statement, is allowed there.


What is a "variable declaration" in Python? Please elaborate.


We may be in danger of disappearing down an unintended 'rabbit hole' 
with this side-discussion (he says, with graceful under-statement).



The basic challenge came from my earlier (and blasé) repetition of the 
Python refrain "everything in Python is an object". Which led to:


<<<
For example, you may say "functions in Python are
objects", but you cannot put a function definition in the head of the
for loop clause.
>>>

Which is logical - to some degree, and in-isolation.

for def a_function( etc )... in iterable/iterator:

does not make sense. The 'head' (a more generic name, where Python says 
"target_list", that refines down to 'something which can identify the 
generated-value'.


So, no, there's an "everything" which (might be) an object but which 
cannot be used in that scenario.



Two "howevers":

However, instead of looking at the narrow clause, (third comment about 
wording not being taken as an whole!!!)* the full quotation was:


<<<
In Python, everything is an object. As long as the LHS is a legal-object 
which  makes sense for the situation, it can be used.

>>>

Context!

However, from the docs: "A function definition defines a user-defined 
function object (see section The standard type hierarchy)". Accordingly, 
is a function-definition an object? No! It defines an object.


That said, does anyone think that something like:

for a_function( etc ) in iterable/iterator:

is acceptable?
- see both Python definition and (full-)quotation.

I've not come-across a language which does allow such - YMMV/mea culpa; 
and am struggling to see how it could possibly be useful.


In-turn, how this discussion could become profitable...


* Looking at the correspondent's email-address (cf 'handle') - and as an 
unfair stereotype, raises the question of issues related to (English) 
language-skills - which, arrogantly implies/assumes that native 
English-speakers are all highly-capable. (?) A negative-interpretation 
is to note his apparent intelligence, but wonder if failing to represent 
others' comments fairly is deliberate, or carelessness. Is there an 
irony in behaving/failing in such, whilst attempting to hold Python's 
structure to some golden-ideal?



Web.Refs:
https://docs.python.org/3/reference/compound_stmts.html#the-for-statement
https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-target_list
https://docs.python.org/3/reference/compound_stmts.html#function-definitions

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


Re: Extract lines from file, add to new files

2024-01-14 Thread dn via Python-list

On 14/01/24 16:48, Chris Angelico wrote:

On Sun, 14 Jan 2024 at 14:43, dn via Python-list  wrote:

Similarly, whilst we could write:

a, b, c = 1, 2, 3



I would only do this when it aligns particularly well with the
algorithm being implemented. For example, you could start a Fibonacci
evaluator with "a, b = 0, 1". Otherwise, there's not all that much
reason to unpack three constants in this way.

(Though I am much more likely to use multiple initialization to set a
bunch of things to the SAME value, lilke "a = b = c = 0".)


Neatly stated!

--
Regards,
=dn

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


Re: Extract lines from file, add to new files

2024-01-13 Thread dn via Python-list

On 13/01/24 00:11, Left Right via Python-list wrote:

To people discussing BNF:

The grammar language Python uses is *very* far from BNF. It's more
similar to PEG, but even then it's still quite far.  Python's grammar
is just its own thing, which makes it harder to read, if you are
already familiar with other more popular formats.


Second time to ameliorate wording-dispute in this thread! The original 
phrase was: "[modified] BNF". Some of us have worked with various forms 
and evolutions of BNF since back in the days of COBOL-60 proposals, and 
know it when we see it!


From the 'book of words': <>>

https://docs.python.org/3/reference/introduction.html#notation

Yes it is hard to read - and even harder to learn-from; which is why 
@Chris gave advice about preferring tutorials/text.


Just because there are other (more popular?) formats, doesn't make the 
one used here 'wrong'. In the same way that Python code differs from 
'the same' in other languages.


Putting it another way: if what Python is doing is wrong in your 
opinion, you are in the wrong place (for you).


That is not to say that Python has everything 'right'. One of my own 
bug-bears is very similar - that the string formatting 'mini-language' 
(https://docs.python.org/3/library/string.html#formatspec) does not 
follow the same rules about white-space as everything covered by the PEG 
Parser.


BTW the PEG Parser is relatively new to Python. IIRC there was comment 
at the time of its first application, that some 'other' areas of Python 
might take a while to be converted-over.




I've also found bugs in Python parser before, so had this turned out


Sorry, didn't recognise your email-handle - not that I'm a Python 
Core-Dev, and pretty much ignore the "Ideas" list these days. Must have 
missed your previous contributions...




to be a real issue, this wouldn't have been the first time.  There are
plenty of weird corners in Python grammar that allow unexpected
programs to parse (and sometimes even run!), and these are very often
connected to assignments, because, in general, assignments in Python
are very elaborate and hard to describe / conceptualize about.  The
most popular example I've even seen used in coding interviews (which I
think is a silly gimmick, but that's kind of the whole point of a lot
of these interviews...) is:

 x = [...]
 for x[i] in x: print(i)

Which is not an assignment by itself, but the "weirdness" results from
the loop syntax sharing definitions with the "destructuring bind"
style of assignment (i.e. where the left-hand side can be an arbitrary
complex expression).


You're right. (also about stupid 'interviewing' ideas) If someone asked 
me this, I'd respond by asking if that was the standard of code they 
work towards - and depending upon that answer would either walk-out or 
refer the matter to a more senior manager!



In Python, everything is an object. As long as the LHS is a legal-object 
which  makes sense for the situation, it can be used.


Also, an identifier (whether x, i, or x[ i ]) should not only be 
considered to be its own object, but is best regarded as a pointer to 
some value. This is how we can have an 'immutable' tuple 'containing' a 
mutable list (for example) - such that elements of that list may be 
changed, despite being 'part of' an immutable construct!


Programs are read by people. If something is a "weirdness", then 
chances-are it won't survive a CodeReview/a professional team's 
expected-standard. Not limited to Python-code!




I was surprised, for example, to learn that "as" in "with_stmt" isn't
shared with "as" in "except_block" (so, from the grammar perspective,
these are two different keywords), and that asterisk in "except_block"
isn't shared with "star_target" (also weird, since you'd think these
should be the same thing).  In general, and by and large, if you look
at Python's grammar there are many "weird" choices that it makes to
describe the language which seem counterintuitive to the programmer
who tries to learn the language from examples (i.e. context-depending
meaning of parenthesis, of asterisk, of period etc.)  Having been
exposed to this, you'd start to expect that some of this weirdness
will eventually result in bugs, or at least in unexpected behavior.


You're right. It is potentially confusing when the same word/symbol is 
used in different contexts.


I've heard similar questions from learners, but not had anyone trying to 
mis-use something extrapolating from how the 'same' is used elsewhere. YMMV!


It's the context part that's important to remember. If someone calls you 
"mate", that has different connotations depending upon whether you're 
friends, you're on a Navy ship, or in a more intimate situation - indeed 
there are some cultures in which the word "mate" is not used to mean 
'friend' at all. Which is (more) right? Which wrong?


Perhaps you're aiming for, or even used to, a more 

Mtg: Object-Oriented VacExcHndlrs (UTC+13)

2024-01-13 Thread dn via Python-list
Let's meet on Wednesday (17Jan, 1600 NZDT (UTC+13), wearing a head-set) 
to talk about Object-Oriented everything. Is O-O worthwhile, or does is 
it just a load of guys running around and getting no-where?


NB this is not a formal PUG-meeting. It's part of the "Vacation 
Exception Handlers" series 
(https://danceswithmice.info/Python/2024/VacExcHndlrs.html) - 
virtual-gatherings for folk left-behind to keep the wheels turning, 
whilst everyone else swans-off sunning themselves...


(non-Kiwis please remember: it's not just school vacation, but 
summer-time down-under. Wish you were here?)


Café-style approach, so there will be no formal presentation. All 
welcome. No presumption of knowledge/skill. This gathering is for 
everyone, from Beginner to Python-Master.



Is Python an Object-Oriented language?
Why does Python use (what appear to be) procedural constructs for so 
many of its core functions, eg len(a_list) rather than a_list.length() 
and sqrt(a_number) rather than a_number.sqrt()?

Why do pythonista say "everything in Python is an object"?
Is it faster to write in an OOP-style and/or does OOP-code run faster? 
If not, why bother?
- insert your question here: What do you want to know? What has been 
bothering you about OOP (or O-O in Python) that you'd like to settle?


To join us (we don't bite!), please RSVP at 
https://www.meetup.com/nzpug-auckland/events/298536620/


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


Re: Extract lines from file, add to new files

2024-01-13 Thread dn via Python-list

On 12/01/24 08:53, Rich Shepard via Python-list wrote:

On Thu, 11 Jan 2024, Piergiorgio Sartor via Python-list wrote:


Why not to use bash script for all?


Piergiorgio,

That's certainly a possibility, and may well be better than python for this
task.


(sitting in a meeting with little to occupy my mind, whilst tidying 
email-InBox came back to this conversation)



In the bare-description of the task, I might agree to sticking with 
BASH. The OP did say that the output from this will become input to a 
sed/mailx task!

(we trust, does not involve spamming innocent folk)

However, that task could also be accomplished in Python. So, unless 
there is an existing script (perhaps) quite why one would choose to do 
half in Python and half in BASH (or...) is a question.



Because this is a Python forum, do the whole thing in one mode - our mode!

Previous suggestions involved identifying a line by its content.

Could use a neat state-transition solution.

However, there is no need to consider the input-data as lines because of 
the concept of "white-space", well-utilised by some of Python's built-in 
string-functions. See code-sample, below.


As mentioned before, the idea of splitting the one file (data-items 
related by serial-progression) and creating two quite-separate 
data-constructs (in this case: one holding the person's name in one file 
and the other the person's email-address in another) which are related 
'across', ie line-by-line, is an architectural error?horror. Such would 
be hard to maintain, and over-time impossible to guarantee integrity. 
Assuming this is not a one-off exercise, see elsewhere for advice to 
store the captured data in some more-useful format, eg JSON, CSV, or 
even put into a MongoDB or RDBMS.



** code

""" PythonExperiments:rich.py
Demonstrate string extraction.
"""

__author__ = "dn, IT Consultant"
__python__ = "3.12"
__created__ = "PyCharm, 14 Jan 2024"
__copyright__ = "Copyright © 2024~"
__license__ = "GNU General Public License v3.0"

# PSL
import more_itertools as it

DATA_FILE = "rich_data_file"
READ_ONLY = "r"
AS_PAIRS = 2
STRICT_PAIRING = True


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

with open( DATA_FILE, READ_ONLY, ) as df:
data = df.read()

data_as_list = data.split()
paired_data = it.chunked( data_as_list, AS_PAIRS, STRICT_PAIRING, )

for name, email_address in paired_data:
# replace this with email-function
# and/or with storage-function
print( name, email_address, )

print("\nTerminating")

** sample output

Calvin cal...@example.com
Hobbs ho...@some.com
...

**

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


Re: Extract lines from file, add to new files

2024-01-11 Thread dn via Python-list

On 12/01/24 12:56, Chris Angelico via Python-list wrote:

On Fri, 12 Jan 2024 at 08:56, Left Right via Python-list
 wrote:


By the way, in an attempt to golf this problem, I discovered this,
which seems like a parser problem:


When you jump immediately to "this is a bug", all you do is make


"seems"!

but yes, it is a (much) less-likely explanation.



yourself look like an idiot. Unsurprisingly, this is NOT a bug, this
is simply that you didn't understand what was going on. The grammar
isn't easy to read, and it's usually better to read the documentation
instead.


Those of us who studied Computer Science may well have been 
taught/expected to learn how to read [modified] BNF - indeed to have 
worked in that (cf coding in Python).


Accordingly, the English text is likely easier to understand, but 
sometimes the BNF offers finer-detail or can be used to clarify some 
mis- or insufficiently-understood aspect of the text. IMHO/YMMV/etc...




(Plus, golfing isn't really a goal in Python, and you didn't  shorten
the code by much at all. Good job.)


I took my hat off to the poster, being prepared to dive-in and do this. 
Accordingly, was more than happy to help set him/her back onto 'the 
straight and narrow'.


(yes it was a BNF-failing - which, credit where credit's due, I think 
was realised at the same time as response was typed)


How many others just want us to do all their thinking for them?
(there's a rude comment about wiping noses - but probably a step too far 
wrt the CoC)


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


Re: Extract lines from file, add to new files

2024-01-11 Thread dn via Python-list

On 12/01/24 10:33, Left Right via Python-list wrote:

By the way, in an attempt to golf this problem, I discovered this,
which seems like a parser problem:

This is what Python tells me about its grammar:

with_stmt:
 | 'with' '(' ','.with_item+ ','? ')' ':' block
 | 'with' ','.with_item+ ':' [TYPE_COMMENT] block
 | ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block
 | ASYNC 'with' ','.with_item+ ':' [TYPE_COMMENT] block

with_item:
 | expression 'as' star_target &(',' | ')' | ':')
 | expression

 From which I figured why not something like this:

with (open('example.txt', 'r'), open('emails.txt', 'w'),
open('salutations.txt', 'w')) as e, m, s:
 for line in e:
 if line.strip():
 (m if '@' in line else s).write(line)

Which, surprise, parsers! But it seems like it's parse is wrong,
because running this I get:

❯ python ./split_emails.py
Traceback (most recent call last):
   File "/home/?/doodles/python/./split_emails.py", line 1, in 
 with (open('example.txt', 'r'), open('emails.txt', 'w'),
open('salutations.txt', 'w')) as e, m, s:
TypeError: 'tuple' object does not support the context manager protocol

It seems to me it shouldn't have been parsed as a tuple. The
parenthesis should've been interpreted just as a decoration.

NB. I'm using 3.11.6.
A series of comma-separated items will be parsed as a tuple (some people 
think it is bounding-parentheses which define).


In this case, the issue is 'connecting' the context-manager "expression" 
with its (as) "target". These should be more-closely paired:-


with ( open( 'example.txt', 'r', ) as e,
   open( 'emails.txt', 'w', ) as m,
   open( 'salutations.txt', 'w', ) as s
   ):

(NB code not executed here)


A data-architecture of having related-data in separated serial-files is 
NOT recommendable!


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


Re: A problem with str VS int.

2023-12-12 Thread dn via Python-list

On 12/12/23 21:22, Steve GS wrote:

With all these suggestions on
how to fix it, no one seems to
answer why it fails only when
entering a two-digit number.
One and three work fine when
comparing with str values. It
is interesting that the
leading 0 on a two digit
worked.  Still, one digit and
three digit work but not two.

This is now more of a
curiosity as I did use the
integer comparisons.



Emphasis on the word "seems"!

Did you try running the code provided earlier? Did you notice that such 
illustrated what happens when using strings which appear as numbers, and 
showed how a three digit number (expressed as a string) may well precede 
a two- (or even a one-) digit number in the same form - and that the 
end-result of the sequence of integers is quite-different to the 
sequence of integer-values expressed as strings!


Why does this happen? Because of the way data is encoded. It is language 
independent. The definition of order or sequence is called "collation".


"Comparisons" establish relative-sequence. You will find some handy 
explanations of how comparisons work (eg equals or less-than) in the 
Python manual.


After working through those three steps, if there's something that's 
still mystifying, please refine the question...



Web.Refs:
https://en.wikipedia.org/wiki/Collation
https://docs.python.org/3/reference/expressions.html?highlight=comparison#value-comparisons
https://docs.python.org/3/howto/sorting.html?highlight=sort


--
Regards,
=dn

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


Re: A problem with str VS int.

2023-12-09 Thread dn via Python-list

On 10/12/23 15:42, Steve GS via Python-list wrote:

  If I enter a one-digit input or a three-digit number, the code works but if I 
enter a two digit number, the if statement fails and the else condition 
prevails.

tsReading = input("   Enter the " + Brand + " test strip reading: ")
 if tsReading == "": tsReading = "0"
 print(tsReading)
 if ((tsReading < "400") and (tsReading >= "0")):
 tsDose = GetDose(sReading)
 print(tsReading + "-" + tsDose)
 ValueFailed = False
 else:
 print("Enter valid sensor test strip Reading.")

I converted the variable to int along with the if statement comparison and it 
works as expected.
See if it fails for you...


It works as expected (by Python)! This is how strings are compared - 
which is not the same as the apparently-equivalent numeric comparison.


Think about what you expect from the code below, and then take it for a 
spin (of mental agility):


values = [ 333, 33, 3, 222, 22, 2, 111, 11, 1, ]
print( sorted( values ) )
strings = [ "333", "33", "3", "222", "22", "2", "111", "11", "1", ]
print( sorted( strings ) )


The application's data appears numeric (GetDose() decides!). 
Accordingly, treat it so by wrapping int() or float() within a 
try-except (and adjusting thereafter...).



"But wait, there's more!"
(assuming implement as-above):

if 0 <= ts_reading < 400:

1 consistent 'direction' of the comparisons = readability
2 able to "chain" the comparisons = convenience
3 identifier is PEP-008-compliant = quality and style

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


Re: How/where to store calibration values - written by program A, read by program B

2023-12-06 Thread dn via Python-list

On 7/12/23 07:12, MRAB via Python-list wrote:

On 2023-12-06 12:23, Thomas Passin via Python-list wrote:

On 12/6/2023 6:35 AM, Barry Scott via Python-list wrote:



On 6 Dec 2023, at 09:32, Chris Green via Python-list 
 wrote:


My requirement is *slightly* more complex than just key value pairs,
it has one level of hierarchy, e.g.:-

    KEY1:
  a: v1
  c: v3
  d: v4
    KEY2:
  a: v7
  b: v5
  d: v6

Different numbers of value pairs under each KEY.


JSON will allow you to nest dictionaries.

{
 'KEY1': {
 'a': v1
 'c': v3
 'd': v4
 }
 'KEY2': {
  'a': v7
  'b': v5
  'd': v6
 }
}

Personally I would not use .ini style these days as the format does 
not include type of the data.


Neither does JSON.  Besides, JSON is more complicated than necessary
here - in fact, your example isn't even legal JSON since lines are
missing commas.

Fun fact - for at least some, maybe most, JSON files, using eval() on
them is hugely faster than using Python's standard JSON library.  I
learned this when I wanted to ingest a large browser bookmarks JSON
file. It wouldn't matter for a much smaller file, of course.


It would be safer if you used literal_eval.


Ah, memories of Python2...

Does this little hack still work?

What about True/False cf true/false?

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


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


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


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


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 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-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: 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: 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: 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: 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: 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-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 construct and taking-up 
time/brain-power. (which is vitally-required for writing/testing Python 
code!)


So, (original code-sample, second line), seeing we ended-up talking 
about 

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


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


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


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

def close(self):
if self._connection:
self._connection.close()


It might be a plan to have several query() methods,

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


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


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


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


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


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 

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


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


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


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


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

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: PyCharm's strict PEP and not so strict?

2023-04-19 Thread dn via Python-list
 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_source=link_campaign=sig-email_content=webmail>
  Virus-free.www.avg.com 
<http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=webmail>

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


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


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

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


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 

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


  1   2   3   4   >