Type hint for "Any But Not None"

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

https://mypy.readthedocs.io/en/stable/protocols.html

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

Okay then, for my use case, this question is moot.