Re: Extract lines from file, add to new files

2024-01-12 Thread Dan Sommers via Python-list
On 2024-01-13 at 02:02:39 +0100,
Left Right via Python-list  wrote:

> Actually, after some Web search.  I think, based on this:
> https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-augtarget
> that in Python you call this "augmented assignment target". The term
> isn't in the glossary, but so are many others.

The Python term, at least colloquially, is "tuple unpacking."

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


Re: Extract lines from file, add to new files

2024-01-12 Thread Chris Angelico via Python-list
On Sat, 13 Jan 2024 at 13:11, Left Right via Python-list
 wrote:
>
>  Very few
> languages allow arbitrary complex expressions in the same place they
> allow variable introduction.

What do you mean by this? Most languages I've worked with allow
variables to be initialized with arbitrary expressions, and a lot of
languages allow narrowly-scoped variables.

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


Re: Extract lines from file, add to new files

2024-01-12 Thread Left Right via Python-list
Actually, after some Web search.  I think, based on this:
https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-augtarget
that in Python you call this "augmented assignment target". The term
isn't in the glossary, but so are many others.

On Sat, Jan 13, 2024 at 1:45 AM Left Right  wrote:
>
> > surprising for me:
>
> Surprise is subjective, it's based on personal experience. Very few
> languages allow arbitrary complex expressions in the same place they
> allow variable introduction. The fact that "i" is not defined is
> irrelevant to this example.  Most programmers who haven't memorized
> Python grammar by heart, but expect the language to behave similar to
> the languages in the same category would be surprised this code is
> valid (i.e. can be parsed), whether it results in error or not is of
> no consequence.
>
> > There's no destructuring going on here
>
> I use the term "destructuring" in the same way Hyperspec uses it.
> It's not a Python term.  I don't know what you call the same thing in
> Python.  I'm not sure what you understand from it.
>
> On Sat, Jan 13, 2024 at 12:37 AM Greg Ewing via Python-list
>  wrote:
> >
> > On 13/01/24 12:11 am, Left Right wrote:
> > >  x = [...]
> > >  for x[i] in x: print(i)
> >
> > I suspect you've misremembered something, because this doesn't
> > do anything surprising for me:
> >
> >  >>> x = [1, 2, 3]
> >  >>> for x[i] in x: print(i)
> > ...
> > Traceback (most recent call last):
> >File "", line 1, in 
> > NameError: name 'i' is not defined
> >
> > There's no destructuring going on here, just assignment to a
> > sequence item.
> >
> > --
> > Greg
> > --
> > https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Extract lines from file, add to new files

2024-01-12 Thread Left Right via Python-list
> surprising for me:

Surprise is subjective, it's based on personal experience. Very few
languages allow arbitrary complex expressions in the same place they
allow variable introduction. The fact that "i" is not defined is
irrelevant to this example.  Most programmers who haven't memorized
Python grammar by heart, but expect the language to behave similar to
the languages in the same category would be surprised this code is
valid (i.e. can be parsed), whether it results in error or not is of
no consequence.

> There's no destructuring going on here

I use the term "destructuring" in the same way Hyperspec uses it.
It's not a Python term.  I don't know what you call the same thing in
Python.  I'm not sure what you understand from it.

On Sat, Jan 13, 2024 at 12:37 AM Greg Ewing via Python-list
 wrote:
>
> On 13/01/24 12:11 am, Left Right wrote:
> >  x = [...]
> >  for x[i] in x: print(i)
>
> I suspect you've misremembered something, because this doesn't
> do anything surprising for me:
>
>  >>> x = [1, 2, 3]
>  >>> for x[i] in x: print(i)
> ...
> Traceback (most recent call last):
>File "", line 1, in 
> NameError: name 'i' is not defined
>
> There's no destructuring going on here, just assignment to a
> sequence item.
>
> --
> Greg
> --
> https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Extract lines from file, add to new files

2024-01-12 Thread Greg Ewing via Python-list

On 13/01/24 12:11 am, Left Right wrote:

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


I suspect you've misremembered something, because this doesn't
do anything surprising for me:

>>> x = [1, 2, 3]
>>> for x[i] in x: print(i)
...
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'i' is not defined

There's no destructuring going on here, just assignment to a
sequence item.

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


Re: Extract lines from file, add to new files

2024-01-12 Thread Left Right via Python-list
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.

I've also found bugs in Python parser before, so had this turned out
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).

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.



Anyways. To the OP: I'm sorry to hijack your question. Below is the
complete program:

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

it turned out to be not quite the golfing material I was hoping for.
But, perhaps a somewhat interesting aspect of this program you don't
see used a lot in the wild is the parenthesis in the "with" head.  So,
it's not a total write-off from the learning perspective.  I.e. w/o
looking at the grammar, and had I have this code in a coding interview
question, I wouldn't be quite sure whether this code would work or
not: one way to interpret what's going on here is to think that the
expression inside parentheses is a tuple, and since tuples aren't
context managers, it wouldn't have worked (or maybe not even parsed as
"as" wouldn't be allowed inside tuple definition since there's no
"universal as-expression" in Python it's hard to tell what the rules
are).  But, it turns out there's a form of "with" that has parentheses
for decoration purposes, and that's why it parses and works to the
desired effect.

Since it looks like you are doing this for educational reasons, I
think there's a tiny bit of value to my effort.

On Fri, Jan 12, 2024 at 8:08 AM Grizzy Adams via Python-list
 wrote:
>
> Thursday, January 11, 2024  at 10:44, Rich Shepard via Python-list wrote:
> Re: Extract lines from file, add to (at least in part)
>
> >On Thu, 11 Jan 2024, MRAB via Python-list wrote:
>
> >> From the look of it:
> >> 1. If the line is empty, ignore it.
> >> 2. If the line contains "@", it's an email address.
> >> 3. Otherwise, it's a name.
>
> If that is it all? a simple Grep would do (and save on the blank line)
> --
> https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


RE: Extract lines from file, add to new files

2024-01-12 Thread Rich Shepard via Python-list

On Fri, 12 Jan 2024, AVI GROSS via Python-list wrote:


But is the solution a good one for some purpose? The two output files may
end up being out of sync for all kinds of reasons. One of many "errors"
can happen if multiple lines in a row do not have an "@" or a person's
name does, for example. What if someone supplied more than one email
address with a comma separator? This may not be expected but could cause
problems.


Avi,

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.

Regards,

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


RE: Extract lines from file, add to new files

2024-01-12 Thread AVI GROSS via Python-list
If the data in the input file is exactly as described and consists of
alternating lines containing a name and email address, or perhaps an
optional blank line, then many solutions are possible using many tools
including python programs.

But is the solution a good one for some purpose? The two output files may
end up being out of sync for all kinds of reasons. One of many "errors" can
happen if multiple lines in a row do not have an "@" or a person's name
does, for example. What if someone supplied more than one email address with
a comma separator? This may not be expected but could cause problems.

Some of the other tools mentioned would not care and produce garbage. Grep
as an example could be run twice asking for lines with an "@" and then lines
without. In this case, that would be trivial. Blank lines, or ones with just
whitespace, might need another pass to be omitted.

But a real challenge would be to parse the file in a language like Python
and find all VALID stretches in the data and construct a data structure
containing either a valid name or something specific like "ANONYMOUS"
alongside an email address. These may be written out as soon as it is
considered valid, or collected in something like a list. You can do further
processing if you want the results in some order or remove duplicates or bad
email addresses and so on. In that scenario, the two files would be written
out at the end.

Python can do the above while some of the other tools mentioned are not
really designed for it. Further, many of the tools are not generally
available everywhere.

Another question is why it makes sense to produce two output files to
contain the data that may not be linked and would not be easy to edit and
keep synchronized such as to remove or add entries. There are many ways to
save the data that might be more robust for many purposes. It looks like the
application intended is a sort of form letter merge where individual emails
will be sent that contain a personalized greeting. Unless that application
has already been written, there are many other ways that make sense. One
obvious one is to save the data in a databases as columns in a table. Other
ones are to write one file with entries easily parsed out such as:

NAME: name | EMAIL: email

Whatever the exact design, receiving software could parse that out as needed
by the simpler act of reading one line at a time.

And, of course, there are endless storage formats such as a CSV file or
serializing your list of objects to a file so that the next program can load
them in and operate from memory on all the ones it wants. The two file
solution may seem simpler but harks back to how some computing was done in
early days when list of objects might be handled by having multiple arrays
with each containing one aspect of the object and updating required
rememebreing to touch each array the same way.. That can still be a useful
technique when some operations being done in a vectoried manner might be
faster than an array of objects, but is more often a sign of poor code.






-Original Message-
From: Python-list  On
Behalf Of Grizzy Adams via Python-list
Sent: Friday, January 12, 2024 1:59 AM
To: Rich Shepard via Python-list ; Rich Shepard

Subject: Re: Extract lines from file, add to new files

Thursday, January 11, 2024  at 10:44, Rich Shepard via Python-list wrote:
Re: Extract lines from file, add to (at least in part)

>On Thu, 11 Jan 2024, MRAB via Python-list wrote:

>> From the look of it:
>> 1. If the line is empty, ignore it.
>> 2. If the line contains "@", it's an email address.
>> 3. Otherwise, it's a name.

If that is it all? a simple Grep would do (and save on the blank line)
-- 
https://mail.python.org/mailman/listinfo/python-list

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


Re: mypy question

2024-01-12 Thread Antoon Pardon via Python-list

Op 29/12/2023 om 16:02 schreef Karsten Hilbert via Python-list:


Am Fri, Dec 29, 2023 at 07:49:17AM -0700 schrieb Mats Wichmann via Python-list:


I am not sure why mypy thinks this

gmPG2.py:554: error: Argument "queries" to "run_rw_queries" has incompatible type 
"List[Dict[str, str]]"; expected
"List[Dict[str, Union[str, List[Any], Dict[str, Any"  [arg-type]
 rows, idx = run_rw_queries(link_obj = conn, queries = 
queries, return_data = True)
   
^~~

should be flagged. The intent is for "queries" to be

a list
of dicts
with keys of str
and values of
str OR
list of anything OR
dict with
keys of str
and values of anything

I'd have thunk list[dict[str,str]] matches that ?

Dict[str, str] means the key type and value type should both be strings,

Indeed, I know that much, list[dict[str, str]] is what is getting
passed in in this particular invocation of run_rw_queries().

For what it's worth here's the signature of that function:

def run_rw_queries (
link_obj:_TLnkObj=None,
queries:list[dict[str, str | list | dict[str, Any]]]=None,
end_tx:bool=False,
return_data:bool=None,
get_col_idx:bool=False,
verbose:bool=False
) -> tuple[list[dbapi.extras.DictRow], dict[str, int] | None]:

Given that I would have thought that passing in
list[dict[str, str]] for "queries" ought to be type safe.
Mypy indicates otherwise which I am not grokking as to why.


but in your
retelling above you indicate lots of possible value types... actually the mypy 
guess
seems to be a pretty good recreation of your psuedo-code description.

I agree that mypy's grasp of my intent from

queries:list[dict[str, str | list | dict[str, Any]]]=None,

into

"List[Dict[str, Union[str, List[Any], Dict[str, Any"

seems accurate. I just don't understand why list[dict[str,
str]] should not pass that construct.


Sorry for the late reaction and may be I am missing something, but I was 
wondering if
your type hint for queries shouldn't be the following.

queries:list[dict[str,str]|dict[str,list]|dict[str,dict[str, dict[str, Ant]]]

My impression at this moment is that you are write something like: dict[str, 
str | int] as
as shorthand for dict[str, str] | dict[str, int]. But those two are different 
types.

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