Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Row, row, row your bits, gently down the stream...


devel / comp.lang.python / Re: imaplib: is this really so unwieldy?

SubjectAuthor
o Re: imaplib: is this really so unwieldy?hw

1
Re: imaplib: is this really so unwieldy?

<mailman.373.1622133772.3087.python-list@python.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=13378&group=comp.lang.python#13378

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: hw...@adminart.net (hw)
Newsgroups: comp.lang.python
Subject: Re: imaplib: is this really so unwieldy?
Date: Thu, 27 May 2021 18:42:43 +0200
Lines: 345
Message-ID: <mailman.373.1622133772.3087.python-list@python.org>
References: <d4d433ff-5de6-31df-4234-e93feea454fc@adminart.net>
<YK15bfs3LoHIdhd8@cskk.homeip.net>
<d8904fa5-3f71-1f21-9d16-6f1105b81551@adminart.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: news.uni-berlin.de ipcQIxdYs+dK/+zDNk1esA0LGgIZ6TxMTKBUDsh3EjWA==
Return-Path: <hw@adminart.net>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
reason="2048-bit key; unprotected key"
header.d=adminart.net header.i=@adminart.net header.b=JyUYqRO2;
dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.000
X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'this:': 0.03; '(which':
0.04; 'def': 0.04; 'learning.': 0.04; 'containing': 0.05;
'fairly': 0.05; 'library.': 0.05; 'parameter': 0.05; 'random':
0.05; 'string': 0.05; 'developer.': 0.07; 'exit': 0.07; 'http':
0.07; 'lets': 0.07; 'mechanism': 0.07; 'modules': 0.07; 'telling':
0.07; 'that?': 0.07; 'thing.': 0.07; 'underlying': 0.07; 'used.':
0.07; 'wrong.': 0.07; 'python.': 0.07; ':-)': 0.09; 'anyway,':
0.09; 'asynchronous': 0.09; 'byte': 0.09; 'choice.': 0.09;
'convert': 0.09; 'effectively': 0.09; 'elsewhere': 0.09; 'forced':
0.09; 'functions,': 0.09; 'git': 0.09; 'library,': 0.09; 'like,':
0.09; 'myself.': 0.09; 'ok,': 0.09; 'parse': 0.09; 'prints': 0.09;
'repo': 0.09; 'responses': 0.09; 'rfc': 0.09; 'string,': 0.09;
'text.': 0.09; 'url-ip:151.101.0.223/32': 0.09; 'url-
ip:151.101.128.223/32': 0.09; 'url-ip:151.101.192.223/32': 0.09;
'url-ip:151.101.64.223/32': 0.09; 'usable': 0.09; 'user.': 0.09;
'yes.': 0.09; 'looks': 0.11; "can't": 0.14; 'import': 0.14;
'talks': 0.14; 'problem': 0.15; '>>>>': 0.16; '_not_': 0.16;
'accessed': 0.16; 'anyway.': 0.16; 'arbitrary': 0.16; 'aside':
0.16; 'assumptions': 0.16; 'async': 0.16; 'basic.': 0.16; 'begun':
0.16; 'boilerplate': 0.16; 'cameron': 0.16; 'charset': 0.16;
'circumstance': 0.16; 'complete,': 0.16; 'discipline': 0.16;
'docs.': 0.16; 'does,': 0.16; 'eg:': 0.16; 'encoding': 0.16;
'encoding,': 0.16; 'everywhere,': 0.16; 'fetch': 0.16; 'fetches':
0.16; 'heavily': 0.16; 'ideal.': 0.16; 'implements': 0.16;
'importing': 0.16; 'incompatible': 0.16; 'indicating': 0.16;
'installed.': 0.16; 'instead.': 0.16; 'main()': 0.16; 'mean:':
0.16; 'means.': 0.16; 'montanaro': 0.16; 'nothing.': 0.16;
'numpy.': 0.16; 'outer': 0.16; 'parsing': 0.16; 'programmed':
0.16; 'protocol,': 0.16; 'protocol.': 0.16; 'pypi.org.': 0.16;
'received:(client did not present a certificate)': 0.16;
'relatively': 0.16; 'responses,': 0.16; 'right.': 0.16; 'says:':
0.16; 'semantics': 0.16; 'simpson': 0.16; 'something.': 0.16;
'specify': 0.16; 'thats': 0.16; 'these.': 0.16; 'things,': 0.16;
'time)': 0.16; 'turns': 0.16; 'upload': 0.16; 'url-
ip:4.31.198/24': 0.16; 'url-ip:4.31/16': 0.16; 'url-ip:4/8': 0.16;
'url:doc': 0.16; 'url:ietf': 0.16; 'url:project': 0.16;
'url:pypi': 0.16; 'worlds': 0.16; 'wrapper': 0.16; 'benefits.':
0.84; 'conservative': 0.84; 'consuming': 0.84; 'fortunately,':
0.84; 'handed': 0.84; 'historic': 0.84; 'hope.': 0.84; 'itself.':
0.84; 'lines,': 0.84; 'ordinary': 0.84; 'programme,': 0.84;
'standalone': 0.84; 'strings': 0.84; 'stuff,': 0.84;
'subject:really': 0.84; 'surprised': 0.84; 'want.': 0.84; 'weird':
0.84; 'powerful': 0.86; 'viewed': 0.90; 'particular,': 0.91;
'promising': 0.91; 'tend': 0.91; 'magic': 0.93; 'subsequent': 0.95
ARC-Seal: i=1; a=rsa-sha256; t=1622133764; cv=none;
d=strato.com; s=strato-dkim-0002;
b=g+7HySyE3vWsDU8jIbIX4cyg7EilnwiNoO3XlcaDcq4N/icFjvRr9wr+xiMHfZvPHn
wp2ihEXn1Pd/nRLD9Cq/LYWWZsTyV4/Vg4AnNyPnGU22W8av4Vb3qRgovcDWRjLqhtT2
/8NJnSbKmFDN6FFGpM71yrqDCnaaJl9p7ofxtZdSh0f5BuOUbrcSm8uLAxoEJcsB+Lsw
B7JBHdRZcGo0zH8Xv0xFgBdJSB6L7G4PogWNpprMSFAt6GROEnWR8Z9Qg8EaFNVOQ6sH
I85Dvz7ZOUv7jAW+lJWFdfQHZeXrhuZuVkKZVIwP4DahdawkHVsz6TLhQ6blZG7YQ9yF
kb6w==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1622133764;
s=strato-dkim-0002; d=strato.com;
h=In-Reply-To:Date:Message-ID:From:References:To:Subject:Cc:Date:From:
Subject:Sender;
bh=2eisCLfNh4GJCxlJdb6bK3n47nlyfZjLtAkcPPIcDVs=;
b=V7C9C0uNzZJesD4fht+5FnuWIGLslcdDNAsFEYBg0m+NoHSnZeVTHTqXYwZeqhgHns
fjF1BlXTFj8Lp7Jh08OBwEW9JogP+Qj7IQ8DljUsV2/dlkwcizmA0Nn4xYhefhUGNAz4
qhxDGqPfWK+m9eaBH3s3HbzLbUlFezZ/7eVzl7tOL3BaQdbo8wi7OajEt3OheD5uoDox
/7oCiZIaseAPSX/DZDULZPykv58o0xsE/wq+5J+sIchlSudrcbwyhRmzD8e/Uu5i42Ct
QSFe9EhEiZwKzyx2B8pXsXIiev4f4+CsoqaxeYp8x2qSM/F9Dhuyof0SmDeRtq7CiOfd
9Pqw==
ARC-Authentication-Results: i=1; strato.com;
dkim=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1622133764;
s=strato-dkim-0002; d=adminart.net;
h=In-Reply-To:Date:Message-ID:From:References:To:Subject:Cc:Date:From:
Subject:Sender;
bh=2eisCLfNh4GJCxlJdb6bK3n47nlyfZjLtAkcPPIcDVs=;
b=JyUYqRO2pIJltvzvdQ91quG2OT6J2vgz+r5Rv2blX9cZKbBRRpvLRZR0qfrmkckvq8
xMjWNPmWQ+PYWyHgQOTijyOuQZJV2sl7hDsS+ZSVKjOB+ZrEFqeVkjqwGI06mUbWJ7NN
sy8pN7rNOFhbqNLnq8KcKR+kEmrTTLWB+w1Onc35QXGCdzAFDiumikgsk0maodHGV6td
1KuBJ6gUl5R5MLKbUed59t8N9ZF7ChtJ3T140B90yf/ZVygf6F+boV6KOUSQulxW1OIh
kRoviP/6BLEHDypDGhddgGi/xwdl+kBWtXL+atsdzasWxsr9BGvCcgRz5Z0kaCLvSNKu
t6Vw==
Authentication-Results: strato.com;
dkim=none
X-RZG-AUTH: ":O2kGeEG7b/pS1Ey9Rna9iAZFrfz26y6zbtmqiE/f0+LThi5xYO8s9RmVPkxvrwQpRPenk8HVxDf4aQ=="
X-RZG-CLASS-ID: mo00
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.10.1
In-Reply-To: <YK15bfs3LoHIdhd8@cskk.homeip.net>
Content-Language: de-DE
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.34
Precedence: list
List-Id: General discussion list for the Python programming language
<python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
<mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
<mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <d8904fa5-3f71-1f21-9d16-6f1105b81551@adminart.net>
X-Mailman-Original-References: <d4d433ff-5de6-31df-4234-e93feea454fc@adminart.net>
<YK15bfs3LoHIdhd8@cskk.homeip.net>
 by: hw - Thu, 27 May 2021 16:42 UTC

On 5/26/21 12:25 AM, Cameron Simpson wrote:
> On 25May2021 19:21, hw <hw@adminart.net> wrote:
>> On 5/25/21 11:38 AM, Cameron Simpson wrote:
>>> On 25May2021 10:23, hw <hw@adminart.net> wrote:
>>>> if status != 'OK':
>>>> print('Login failed')
>>>> exit
>>>
>>> Your "exit" won't do what you want. I expect this code to raise a
>>> NameError exception here (you've not defined "exit"). That _will_ abort
>>> the programme, but in a manner indicating that you're used an unknown
>>> name. You probably want:
>>>
>>> sys.exit(1)
>>>
>>> You'll need to import "sys".
>>
>> Oh ok, it seemed to be fine. Would it be the right way to do it with
>> sys.exit()? Having to import another library just to end a program
>> might not be ideal.
>
> To end a programme early, yes. (sys.exit() actually just raises a
> particular exception, BTW.)
>
> I usually write a distinct main function, so in that case one can just
> "return". After all, what seems an end-of-life circumstance in a
> standalone script like yours is just an "end this function" circumstance
> when viewed as a function, and that also lets you _call_ the main
> programme from some outer thing. Wouldn't want that outer thing
> cancelled, if it exists.
>
> My usual boilerplate for a module with a main programme looks like this:
>
> import sys
> ......
> def main(argv):
> ... main programme, return like any other function ...
> .... other code for the module - functions, classes etc ...
> if __name__ == '__main__':
> sys.exit(main(sys.argv))
>
> which (a) puts main(0 up the top where it can be seen, (b) makes main()
> an ordinary function like any other (c) lets me just import that module
> elsewhere and (d) no globals - everything's local to main().
>
> The __name__ boilerplate at the bottom is the magic which figures out if
> the module was imported (__name__ will be the import module name) or
> invoked from the command line like:
>
> python -m my_module cmd-line-args...
>
> in which case __name__ has the special value '__main__'. A historic
> mechanism which you will convince nobody to change.

Thanks, that seems like good advice.

> You'd be surprised how useful it is to make almost any standalone
> programme a module like this - in the medium term it almost always pays
> off for me. Even just the discipline of shoving all the formerly-global
> variables in the main function brings lower-bugs benefits.

What do you do with it when importing it? Do you somehow design your
programs as modules in some way that makes them usable as some kind of
library funktion?

>>> I've done little with IMAP. What's in msgnums here? Eg:
>>> print(type(msgnums), repr(msgnums))
>>> just so we all know what we're dealing with here.
>>
>> <class 'list'> [b'']
>>
>>>> message_uuids = []
>>>> for number in str(msgnums)[3:-2].split():
>>>
>>> This is very strange. [...]
>> Yes, and I don't understand it. 'print(msgnums)' prints:
>>
>> [b'']
>>
>> when there are no messages and
>>
>> [b'1 2 3 4 5']
>
> Chris has addressed this. msgnums is list of the data components of the
> IMAP response. By going str(msgnums) you're not getting "the message
> numbers as text" you're getting what printing a list prints. Which is
> roughly Python code: the brakcets and the repr() of each list member.

Well, of course I exepect to get message numbers returned from such a
library function, not the raw imap response. What is the library for
when I have to figure it all out by myself anyway.

> Notice that the example code accessed msgnums[0] - that is the first
> data component, a bytes. That you _can_ convert to a string (under
> assumptions about the encoding).

And of course, I don't want to randomly convert bytes into strings ...

> By getting the "str" form of a list, you're forced into the weird [3:-2]
> hack to ttrim the ends. But it is just a hack for a transcription
> mistake, not a sane parse.

Right, thats why I don't like it and is part of what makes it so unwieldy.

>> So I was guessing that it might be an array containing a single a
>> string and that refering to the first element of the array turns into
>> a string with which split() can used. But 'print(msgnums[0].split())'
>> prints
>>
>> [b'1', b'2', b'3', b'4', b'5']
>
> msgnums[0] is bytes. You can do most str things with bytes (because that
> was found to be often useful) but you get bytes back from those
> operations as you'd hope.

As someone unfamiliar with python, I was wondering what this output
means. It could be items of an array that are bytes containing numbers,
like, in binary, 00000001, 00000010, and so on. That's more like what I
would expect and not something I would want to convert into a string.

>> so I can only guess what that's supposed to mean: maybe an array of
>> many bytes? The documentation[1] clearly says: "The message_set
>> options to commands below is a string [...]"
>
> But that is the parameter to the _call_: your '(UID)' parameter.

No, it's not a uid. With library, I haven't found a way to get uids.
The function to call reqires a string, not bytes or an array of bytes.

The included example contradicts the documentation and leaves potential
users of the library to guessing.

>> I also need to work with message uids rather than message numbers
>> because the numbers can easily change. There doesn't seem to be a way
>> to do that with this library in python.
>
> By asking for UIDs you're getting uids. Do they not work in subsequent
> calls?

How do you force the library to give uids instead of message numbers,
and how do you make it do something with a particular message by uid?

>> So it's all guesswork, and I gave up after a while and programmed what
>> I wanted in perl. The documentation of this library sucks, and there
>> are worlds between it and the documentation for the libraries I used
>> with perl.
>
> I think you're better of looking for another Python imap library. The
> imaplib was basic functionality to (a) access the rpotocol in basic form
> and (b) conceal the async stuff, since IMAP is an asynchronous protocol.
>
> You can in fact subclass it to do better things. Other library might do
> thatm or they might have written their own protocol implementations.

I haven't really found a better one.

>> That doesn't mean I don't want to understand why this is so unwieldy.
>> It's all nice and smooth in perl.
>
> But using what library? Something out of CPAN? Those are third party
> libraries, not Perl's presupplied stuff.
The libraries I used with perl all come with Fedora, so they are
presupplied and only need to be installed. You can find them on cpan as
well. It's very convenient.

> The equivalent for Python is
> pypi.org. Look there.

Yes, someone pointed it out, and I did. They have an imap-tools library
which looks most promising at first, and its documentation tells me that
you do can some IMAP operations with messages --- and nothing with
messages themselves, like getting from the server.

So it seems that IMAP support through python is virtually non-existent.

>>> It is just breaking apart data[0] into strings which were separated by
>>> whitespace in the response. And then using those same strings as keys
>>> for the .fecth() call. That doesn't seem complex, and in fact is blind
>>> to the format of the "message numbers" returned. It just takes what it
>>> is handed and uses those to fetch each message.
>>
>> That's not what the documentation says.
>
> The _example code_ is blind to them, whatever the semantics of the docs.
> It just gets the uids and fetches with them. Aside from .split(),
> there's no parsing or deep understanding of the uid.

There is no telling what might happen to the messages when using
functions that randomly convert bytes in weird ways and that contradict
the documentation. Why would I trust this library not to accidentially
delete all my emails or to not do other harmful things?

>>> IMAP's quite complex. Have you read RFC2060?
>>>
>>> https://datatracker.ietf.org/doc/html/rfc2060.html
>>
>> Yes, I referred to it and it didn't become any more clear in
>> combination with the documentation of the python library.
>
> IMAP's like that :-)


Click here to read the complete article
1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor