Re: PEP668 / pipx and "--editable" installs

2023-09-16 Thread Karsten Hilbert via Python-list
Am Sat, Sep 16, 2023 at 02:17:19PM +1200 schrieb Rimu Atkinson via Python-list:

> Everyone uses virtual environments.

Umm, like, no.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-03 Thread Karsten Hilbert via Python-list
Am Thu, Nov 02, 2023 at 09:35:43PM - schrieb Jon Ribbens via Python-list:

Regardless of ...

> Because pip barely plays well by itself, let alone with other package
> managers at the same time.

... being true ...

> > I do only install a few things using pip.
>
> Are they not available in your system's package manager?

... this clearly often answers to "no" for applications of
any complexity.

Is there a suggested proper path to deal with that (Debian is
of interest to me here) ?

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-04 Thread Karsten Hilbert via Python-list
Am Thu, Nov 02, 2023 at 04:07:33PM -0600 schrieb Mats Wichmann via Python-list:

> >So they now have only python3 and there is no python executable in
> >PATH.
>
> FWIW, for this you install the little stub package python-is-python3. 
> Especially if you
> want to keep a python2 installation around - "python" will still be python3 
> in this
> case.

Since you seem knowledgeable in this area: Do you know of a
resource for learning the *canonical* way of packaging a
Python application for installation via apt which

- needs some packages available via apt
- needs some packages only available via pip
- needs some packages newer than what is available via apt

?

Thanks,
Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Aw: Re: pip/pip3 confusion and keeping up to date

2023-11-07 Thread Karsten Hilbert via Python-list
> > .From all the posts I gather the answer to my question is
> > "simply": unpackaged-but-needed modules need to be packaged.
>
> I think there is one aspect that isn't getting consideration here.  And
> that is whether or not you want these packages installed in the default
> system Python install.  You might not.

Indeed, which is why all the fuzz about how to fill-in a venv from pip while
installing with apt :-)

With "properly" packaged modules one wouldn't risk (that much) system
breakage, at any rate.

>  Maybe you want to get the latest
> possible version of super-dooper-gui-helper, but one of its dependencies
> doesn't play well with the system Python libraries. Or ... but you get
> the point.  There are probably many cases where you want *not* to
> install into the system Python world.  So you would need to come up with
> an APT-based installer that doesn't do that.
>
> Obviously it's not unthinkable;

Certainly not, it's just that I had hoped someone goes: look here
and all of this ...

> it is just one more thing to figure out.

... has been thought through before.

Thanks,
Karsten
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-05 Thread Karsten Hilbert via Python-list
Am Sun, Nov 05, 2023 at 03:00:41PM + schrieb Chris Green via Python-list:

> >   * contact every single maintainer of every single one of the packages
> > that needs updating and persuade them to update their packages and
> > reassure them that you are getting all the other package maintainers
> > to update their packages accordingly and that you have a plan and
> > that you know what you're doing
> >
> >   ... screen fades to black, title card "3 years later", fade in to ...
> >
> >   * publish your package
> >
> Surely it's not that bad, the vast bulk of Debian, Ubuntu and other
> distributions are installed via systems that sort out dependencies once
> given a particular package's requirements.  Python is surely not
> unique in its dependency requirements.

Oh, Debian does just fine in resolving dependencies it knows
about within its .deb package universe. The problem arises
when there's unpackaged modules required. The only answer
seems to be to package such modules oneself.

If that's been conquered a venv isn't even needed anymore.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-05 Thread Karsten Hilbert via Python-list
Am Fri, Nov 03, 2023 at 01:53:32PM - schrieb Jon Ribbens via Python-list:

> >> Are they not available in your system's package manager?
> >
> > ... this clearly often answers to "no" for applications of
> > any complexity.
> >
> > Is there a suggested proper path to deal with that (Debian is
> > of interest to me here) ?
>
> Yes, as previously mentioned, use virtual environments.
>
> These days they don't even need to be "activated". For package 'foo'
> for example you could create /usr/local/lib/foo, under which you would
> create a virtual environment and install the 'foo' package inside it,
> and then you could do:
>
> ln -s /usr/local/lib/foo/env/bin/foo /usr/local/bin/foo
>
> and then you could just type 'foo' to run it.

This all being nice and well, but:

How does one "fill" that venv with packages from pip during

apt-get install python3-app-of-interest

?

Is the suggested way really to pip-install into this venv
during apt-get install ?

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-05 Thread Karsten Hilbert via Python-list
Am Fri, Nov 03, 2023 at 05:26:06PM +0100 schrieb Dieter Maurer:

> Karsten Hilbert wrote at 2023-11-3 14:47 +0100:
> > ...
> >> Are they not available in your system's package manager?
> >
> >... this clearly often answers to "no" for applications of
> >any complexity.
> >
> >Is there a suggested proper path to deal with that (Debian is
> >of interest to me here) ?
>
> Complex applications may maintain a set of "known workable versions"
> associated with the application's releases.
> They may describe those "known workable versions" in a `pip` constraint file.
> In this case, you can upgrade to a new application release
> by using this constraint file.

Hello Dieter,

do you happen to know where to read up on how to fit a pip
constraint file into a Debian package creation workflow ?

Thanks,
Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-06 Thread Karsten Hilbert via Python-list
Am Mon, Nov 06, 2023 at 01:17:11AM - schrieb Jon Ribbens via Python-list:

> >> >> Are they not available in your system's package manager?
> >> >
> >> > ... this clearly often answers to "no" for applications of
> >> > any complexity.
> >> >
> >> > Is there a suggested proper path to deal with that (Debian is
> >> > of interest to me here) ?
> >>
> >> Yes, as previously mentioned, use virtual environments.
> >>
> > How does one "fill" that venv with packages from pip during
> >
> > apt-get install python3-app-of-interest
> >
> > ?
> >
> > Is the suggested way really to pip-install into this venv
> > during apt-get install ?
>
> I don't know what you mean by that. But if you install the apt packages
> and then create your venv with --system-site-packages then I believe
> your venv should be able to see the apt packages and import them.

The problem is when there's modules not available via apt as
packages. In that case on needs to either package them or pip
them into the venv suggested above.

When they are apt-gettable no venv is needed in the first
place. One would just install the application script like any
other binary, and which loads apt-installed modules just so.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-06 Thread Karsten Hilbert via Python-list
Am Mon, Nov 06, 2023 at 08:58:00AM +0100 schrieb Dieter Maurer:

> I know that debian packagers create debian packages
> from Python distributions not using the approach sketched above
> and likely they have their reasons.
>
> You might want to discuss this on an `apt` related mailing list.

Yeah, I guess. I know all this stuff about python modules
being packaged for Debian and how apt handles dependencies
etc etc.

I had just hoped someone here might have a handy pointer for
how to deal with modules having to be installed from pip for
use with an apt-installed python-based application.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: pip/pip3 confusion and keeping up to date

2023-11-06 Thread Karsten Hilbert via Python-list
Am Mon, Nov 06, 2023 at 02:43:47PM -0700 schrieb Mats Wichmann via Python-list:

> >I had just hoped someone here might have a handy pointer for
> >how to deal with modules having to be installed from pip for
> >use with an apt-installed python-based application.
>
> That just shouldn't happen - such packages are supposed to be 
> dependency-complete within
> the packaging universe in question.

Yep, that's the preferable ideal world.

Which doesn't happen (but that's not the fault of anyone
around here, no harm intended).

.From all the posts I gather the answer to my question is
"simply": unpackaged-but-needed modules need to be packaged.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Aw: Re: Any possible type alias that can also set a default value for a function arg?

2023-10-19 Thread Karsten Hilbert via Python-list
> > or something like that. Basically, any way to avoid writing `= None` over 
> > and over again.
>
> Fundamentally no, at least not without some shenanigans. Type hints do
> not affect the regular running of the code,

Except when they do ;-)

... depending on what counts as (valid) code ...

In Python a distinction can be made between "runnable" and "valid" :-D

Karsten

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


type annotation vs working code

2023-09-30 Thread Karsten Hilbert via Python-list
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) ?

Thanks,
Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-09-30 Thread Karsten Hilbert via Python-list
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?

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.

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

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

Which seems akin constructs for generating compatibility
between versions.

It seems the answer is being pointed to in Matts response.

It just mightily surprised me.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-10-01 Thread Karsten Hilbert via Python-list
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 :-)

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 ?


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

Regards,
Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Aw: Re: Re: Re: Any possible type alias that can also set a default value for a function arg?

2023-10-19 Thread Karsten Hilbert via Python-list
> > As per my recent foray into abusing existence-checking for Singleton 
> > assurance
> > along such lines as
> >
> > >>> try: self.initialized
> > >>> except AttributeError: print('first instantiation'); self.initialized = 
> > >>> True
> >
> > and then changing that to
> >
> > >>> try: self.initialized:bool
>
> But that's not equivalent code.

I learned as much (RHS vs LHS).

But it did not _intuitively_ resonate with the sentiment
"type annotation does not change the running of code".

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


Aw: Re: Re: Any possible type alias that can also set a default value for a function arg?

2023-10-19 Thread Karsten Hilbert via Python-list
> > > Fundamentally no, at least not without some shenanigans. Type hints do
> > > not affect the regular running of the code,
> >
> > Except when they do ;-)
> >
> > ... depending on what counts as (valid) code ...
> >
> > In Python a distinction can be made between "runnable" and "valid" :-D
> >
>
> Can you give a counter-example?

As per my recent foray into abusing existence-checking for Singleton assurance
along such lines as

>>> try: self.initialized
>>> except AttributeError: print('first instantiation'); self.initialized = True

and then changing that to

>>> try: self.initialized:bool

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


Re: type annotation vs working code

2023-10-04 Thread Karsten Hilbert via Python-list
Am Wed, Oct 04, 2023 at 05:25:04PM +1300 schrieb dn via Python-list:

> 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

This, in my case.

> and so, returning to the matter of 'readability':
>
> - the name "Borg" de-railed comprehension
>
> - _instances:dict = {} implied the tracking of more than one

Child classes, yes, each being a Singleton.

> or a Singleton() class defined, which is then sub-classed, ie
>
> class Something( Singleton ):

Could have been but the legacy codebase came with Borg ...

> - from there, plenty of 'templates' exist for Singletons,

...  which was taken from the Web ages ago.

> - this article (https://python-patterns.guide/gang-of-four/singleton/)

Reading.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Aw: Re: Re: mypy question

2023-12-30 Thread Karsten Hilbert via Python-list
> I'm fairly sure your database queries don't actually give you strings or
> dicts, right?  You probably get lists (or iterators) of tuples and
> somewhere you convert them to the arguments you are feeding to
> run_queries().

Ah, no, those queries are enshrined within the middleware as Python strings
with placeholdders. When in need of being run they are assembled into
a list of dicts-enriched-with-arguments-per-query (and fed to run_queries()).

As to what queries *give* me: I have set up psycopg2 to, indeed, hand
me a list of dicts (DictRow instances, that is). Those are then used
in display rather than being fed to run_queries().

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


Aw: Re: mypy question

2023-12-30 Thread Karsten Hilbert via Python-list
Dear Thomas,

thanks for taking the time to look into my issue.

Maybe it helps if I explain what I want (sorry that my web mailer does not 
respect
indentation, I will insert dots).

I want a function to run SQL queries:

run_queries(conn, queries):
...for q in queries:
..conn.execute(q)

I now want to add type hints such that my large codebase can
be checked for silly doings. First, queries is to be a list
of the SQL to run:

run_queries(conn, queries:list):

Then, each list entry can be

...a string holding simple, complete SQL (say "SELECT 1")

run_queries(conn, queries:list[str]):

or

...a dict holding the SQL and arguments for parameters

run_queries(conn, queries:list[dict]):

So, taken together:

run_queries(conn, queries:list[str|dict]):

(yes, this is in Python 3.11/3.12)

Now, when it is a list of dicts I want to further constrain the
dicts. Each is to contain the keys "SQL" and "args". So the keys
are of type str. The values for the keys will be of various types,
such that I chose Any as pseudo-type, so that each list entry that
is of type dict should be dict[str, Any], hence:

queries = [{'SQL': 'SELECT %(value)s', 'args': {'value': 1}}]

and

run_queries(conn, queries:list[str|dict[str, Any]]):

If I now call this function with a simple SQL query:

SQL_query = 'SELECT 1'  # should be type str ?
queries = [SQL_query]   # should be type list[str] ?
run_queries(conn, queries = queries)

and run mypy over that (at least inside my complex codebase) I will
get a type mismatch being hinted at.

So far I don't grasp at which point my reasoning above is faulty.

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


Aw: Re: Re: mypy question

2023-12-30 Thread Karsten Hilbert via Python-list
> It occurs to me that you could simplify things if you converted those
> plain query strings to dicts:
>
> 'SELECT 1' --> {'SQL': 'SELECT 1'}

Ha, indeed. There's likely not that many "simple string SQL queries"
in that codebase so I shall take it as an opportunity to refactor them.

So, at least that much good has come from the mypy hint ;-)

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


Aw: Re: mypy question

2023-12-30 Thread Karsten Hilbert via Python-list
Hi Greg,

> dict[str, str] is not a subtype of dict[str, str | something_else]
> because you can assign a value of type something_else to the latter
> but not the former.

I understand what you are saying but I do not yet understand why this
applies to my situation.

I don't have Python at hand currently, so I'll write untested pseudocode:

def print_greeting(greeting:int|str):
   print(greeting)

print_greeting('hello')

The above snippet should be equivalent to my more complicated code over
which mypy complains to the equivalent of

   "input" is of type "str"
   but expected type "Union[str,int]

I do understand that "str" is formally more narrow than "Union [str,int]" and
the type system has every right to not consider them equivalent.

However, this seems like a very common use case: "allow passing in either str 
or int
and have type checking pass either input as valid" -- yet mypy doesn't seem
to share that idea.

Or else there's something I haven't wrapped my head around yet. But what ?

Karsten

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


Re: mypy question

2023-12-31 Thread Karsten Hilbert via Python-list
Thanks to all. I ended up using Sequence for the list part
and Mapping for the dict part, which does require "import
typing" which I would rather have avoided.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


mypy question

2023-12-29 Thread Karsten Hilbert via Python-list
Hi all,

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 ?

This is on Python 3.11.2 with mypy 1.0.1 on Debian.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mypy question

2023-12-29 Thread Karsten Hilbert via Python-list
Am Fri, Dec 29, 2023 at 01:15:29PM +0100 schrieb Karsten Hilbert 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 ?
>
> This is on Python 3.11.2 with mypy 1.0.1 on Debian.

For completeness, this was the mypy call signature:

mypy --pretty --allow-redefinition --no-strict-optional 
--ignore-missing-imports --follow-imports silent --show-error-codes 
--warn-unused-ignores gmPG2.py

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mypy question

2023-12-29 Thread 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.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mypy question

2023-12-29 Thread Karsten Hilbert via Python-list
Am Fri, Dec 29, 2023 at 11:04:59AM -0700 schrieb Mats Wichmann via Python-list:

> >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.
>
> ah... didn't grok what you were asking, sorry - ignore my attempt then.

Never mind, the attempt to help is appreciated.

> So you are passing something that has been typed more
> narrowly than the function parameter.

That would then sort of skirt on violation of the Liskov
principle, of which I learned while trying to research this
mypy behaviour.

However, I would not think the above to be a narrowing-down
as it just *selects* one of the explicitely "legal" options.

list[dict[str, str | list | dict[str, Any]]]

should AFAICT expand to:

list[dict[str, dict[str, Any]]]

OR

list[dict[str, list]]

OR

list[dict[str, str]]

the last of which should provide coverage of

[{'some key': 'some value'}]

> Can you use a TypeGuard here?

Not from what I understand about them...

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mypy question

2024-01-13 Thread Karsten Hilbert via Python-list
Am Fri, Jan 12, 2024 at 02:23:43PM +0100 schrieb Antoon Pardon via Python-list:

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

ne'er mind ya

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

I do.

> But those two are different types.

A-ha ! In what way ?

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: mypy question

2024-01-13 Thread Karsten Hilbert via Python-list
Am Sat, Jan 13, 2024 at 09:20:00PM +0100 schrieb Karsten Hilbert via 
Python-list:

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

Wait, not really. Let me give an example. Here's three times
the same query (as far as PostgreSQL is concerned, after
having been passed through psycopg2):

queries = [
{
'SQL': 'SELECT 1'
},
{
'SQL': 'SELECT %s',
'args': [1]
},
{
'SQL': 'SELECT %(value)s',
'args': {'value': 1}
}
]

The value for key "SQL" will always be str-like.

The value for "args" can be a list or a dict itself.

If "args" is a dict it will be of type [str, Any].

That's what I am trying to tell mypy.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list


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

2024-01-30 Thread Karsten Hilbert via Python-list


> > Why not foxus on just the part you think you are better off using python,
> > namely personalization ?
> >
> > Create personalized files and send them with your trusted mailx solution ?
>
> Karsten,
>
> Too much time. And while mailx accepts the '-a' option for attachments but
> has none for individual salutations.

It doesn't need to. It just sends the (pre-personalized-by-Python) mail files.

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


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

2024-01-30 Thread Karsten Hilbert via Python-list
> On Tue, 30 Jan 2024, Karsten Hilbert wrote:
>
> > It doesn't need to. It just sends the (pre-personalized-by-Python) mail 
> > files.
>
> Karsten,
>
> In which case, I might as well have Python format and send the messages. :-)

Certainly. But it seems you are wrestling with Python. Might as well reduce the 
attack surface.

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


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

2024-01-30 Thread Karsten Hilbert via Python-list
> For 30 years I've used a bash script using mailx to send messages to a list
> of recipients. They have no salutation to personalize each one. Since I want
> to add that personalized salutation I decided to write a python script to
> replace the bash script.

Why not foxus on just the part you think you are better off using python, namely
personalization ?

Create personalized files and send them with your trusted mailx solution ?

That'll take out wrestling with smptlib et al.

Karsten

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


Re: Terminal Emulator (Posting On Python-List Prohibited)

2024-05-19 Thread Karsten Hilbert via Python-list
Am Sun, May 19, 2024 at 10:45:09PM +0100 schrieb Barry via Python-list:

> > On 18 May 2024, at 16:27, Peter J. Holzer via Python-list 
> >  wrote:
> >
> > I don't think Linux users have to deal with venvs
>
> Modern debian (ubuntu) and fedora block users installing using pip.
> You must use a venv to pip install packages from pypi now.

Which makes one wonder how one is supposed to package Python
applications requiring modules not yet packaged by Debian.

Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B
-- 
https://mail.python.org/mailman/listinfo/python-list