Is there a way to specify that a certain parameter can be anything except None?
Better still if we can specify a “Not one of these types” annotation.
Is there a way to specify that a certain parameter can be anything except None?
Better still if we can specify a “Not one of these types” annotation.
I don’t think that type hinting currently supports “not these types”.
Normally it wouldn’t come up. You wouldn’t say:
“An int or a string, but not a string”
for obvious reasons. It possibly makes sense to disallow a subclass:
“An int, but not this subclass of int”
but that would violate some pretty deep assumptions of object oriented
programming so I’m not sure type checkers would want to support it or
that we should encourage that sort of code.
It is hard for me to imagine a scenario where you would accept literally
any arbitrary object except None or some other small set of types:
“Its okay if its an int, or a list, or NotImplemented, or Ellipsis, or a
HTTPServer object, or a Pandas dataframe object, or a EmployeeRecord
object, or a function, or an iterator, or a ValueError exception object,
or literally anything else, except for None.”
What are you doing with this parameter that it can accept NotImplemented
and HTTPServer but not None?
Check aiosmtpd
package, the recommended replacement for smtpd
as stated explicitly in the Python documentation.
The aiosmtpd.smtp.SMTP
class requires a handler
object which will be inspected for hooks. This handler object can be anything except None
.
I’m not an aiosmtpd
expert, but looking at the documentation it seems to me that while there is no restriction, the only “useful” stuff that you can pass are instance of “Handlers”, that is, that implements at least one of the method defined in Handlers — aiosmtpd 1.4.1 documentation
A “clunky” (I see 14 hooks) but possible way is to define a protocol for each supported hook and define an “Handler” as the union of the protocols.
I don’t think that your description is accurate. The docs for
the aiosmtpd.smtpd.SMTPD constructor gives a handler parameter:
https://aiosmtpd.readthedocs.io/en/latest/smtp.html#aiosmtpd.smtp.SMTP
that says:
“An instance of a handler class that optionally can implement Handler
Hooks.”
There is nothing I can see that says that the handler can be “anything
except None”, or that you could pass a float, a list or a Pandas
dataframe as the handler. Or even that None is prohibited.
Since floats, lists and dataframes don’t have those hooks, they aren’t
useful handlers. But I don’t know if the SMTP class will reject them,
raising an exception, or if it will silently allow them and not call any
hooks.
This:
https://aiosmtpd.readthedocs.io/en/latest/handlers.html#hooks
says that says that the hook methods must be coroutines. The
depreciated server hooks:
https://aiosmtpd.readthedocs.io/en/latest/smtp.html#server-hooks
are also coroutines.
If you are referring to something else, could you link directly to the
relevant docs?
It sounds to me that handlers are defined by the protocol, not by type.
A handler can be any class so long as it defines the right methods. In
other words, handlers are duck-typed. If an object has the correct
methods, it doesn’t matter what the class is.
So it seems to me that the correct interface here is not “anything but
None” but “anything that supports this protocol”.
Hmm, you’re right.
I didn’t realize that one can do getattr(o, "something", None)
when o = None
, or that dir(None)
is actually valid
Okay then, for my use case, this question is moot.
The first half of this post (i.e. “…a way to specify that a certain parameter can be anything except None”) would indeed be useful. We have typing.Any
, we have typing.Optional
… why not have something like typing.Some
or something like that, meaning that a value is of any type except None? It’s perfectly fine to conceive.
I would also like typing.Some
: I have some kind of factory method that returns one of many classes or None (if no handler is found), say Union[None, ClassA, ClassB, ClassC]
. Now, in a different module, I have a method that ensures that there is a valid handler, calling the factory method and asserting that the result is not None. I would like to specify that it cannot return None (because pylance does not work it out itself), but I do not want to list all the possible handler classes, which are an implementation detail of a different module.
I would really like this as well.