typing icon indicating copy to clipboard operation
typing copied to clipboard

advanced SimpleNamespace typing

Open itajaja opened this issue 5 years ago • 9 comments

the same way we now have TypedDict, it would be nice to have typed SimpleNamespace with equivalent semantics, so that nested structures can be easily checked. eg

class MySubType(TypedSimpleNamespace):
   bar: int

class MyType(TypedSimpleNamespace):
   foo: MySubType

# correct
a: MyType = SimpleNamespace(foo=SimpleNamespace(bar=1))
# incorrect, `bar` should be a number
a: MyType = SimpleNamespace(foo=SimpleNamespace(bar='abc'))

itajaja avatar Nov 26 '19 16:11 itajaja

I think Protocol can basically be used as your proposed TypedSimpleNameSpace.

JelleZijlstra avatar Nov 26 '19 18:11 JelleZijlstra

as far as I can tell, protocols can be used to cast the simple namespace into, but it won't help me typechecking SimpleNamespce, like in my example snippet. can you provide an example when using protocols where the correct line would succeed and the wrong line would file? I don't believe it's possible without adding a specific SimpleNamespace type

itajaja avatar Nov 26 '19 18:11 itajaja

I think Protocol can basically be used as your proposed TypedSimpleNameSpace.

Almost, but not completely. IIUC auto-generated __init__() signature is important. On the other hand, the latter can be added when support for key types is added.

ilevkivskyi avatar Nov 26 '19 18:11 ilevkivskyi

the latter can be added when support for key types is added.

thanks @ilevkivskyi can you link to related resources about it?

itajaja avatar Nov 26 '19 18:11 itajaja

We don't have a "centralized" issues to track this, but you can watch https://github.com/python/mypy/issues/7856 and/or https://github.com/python/mypy/issues/7790

ilevkivskyi avatar Nov 26 '19 18:11 ilevkivskyi

I expect this to work:

from typing import Protocol
from types import SimpleNamespace

class Person(Protocol):
    @property
    def name(self) -> str: ...
    
    @property
    def age(self) -> int: ...

def get_person() -> Person:
    return SimpleNamespace(
        name="Alice",
        age=40
    )

But I am not getting any type checking whatsoever.

bartenra avatar Jun 08 '22 09:06 bartenra

I use SimpleNamespace for one-off cases where specifying a dataclass or Protocol would be unnecessary boilerplate. I'd like to be able to type SimpleNamespace as a generic:

def returns_namespace() -> SimpleNamespace[int]:
    return SimpleNamespace(a=1, b=2)

This is not possible at the moment as SimpleNamespace accepts no type arguments, but it'll be nice to have this as a first step before TypedDict-level typing.

jace avatar Nov 23 '22 19:11 jace

def returns_namespace() -> SimpleNamespace[int]:
    return SimpleNamespace(a=1, b=2)

That should be -> SimpleNamespace[[int, int]] (cf. Callable)

szabi avatar Mar 24 '23 10:03 szabi

Documentation of SimpleNamespace mentions:

However, for a structured record type use namedtuple() instead.

Shouldn't that cover the usecases brought up here?

antonagestam avatar Mar 27 '23 06:03 antonagestam