I want to create a new type derived from ObjectId in similar way as is described in documentation for new type UserId derived from int:
from bson import ObjectId
UserId = NewType('UserId', ObjectId)
But Mypy gives Argument 2 to NewType(...) must be subclassable (got "Any").
There is written in documentation:
NewType accepts exactly two arguments. The first argument must be a string literal containing the name of the new type and must equal the name of the variable to which the new type is assigned. The second argument must be a properly subclassable class, i.e., not a type construct like Union, etc.
It is not clear what _properly subclassable class_ means and why ObjectId is not _properly subclassable class_. Could please someone clarify this to me and in documentation?
The reason is presumably that mypy can't find stubs for bson, so it treats all names from it as Any, and it disallows using NewType on Any. I agree that this would be useful to mention in the docs.
I think we should actually allow Any as a base class for NewType. The logic is that Any should not cause any _new_ errors (of course unless one uses some --disallow-any-* flags).
But in addition we should clarify the docs.
Then we should also update PEP 484.
On Fri, Apr 19, 2019 at 4:29 PM Ivan Levkivskyi notifications@github.com
wrote:
I think we should actually allow Any as a base class for NewType. The
logic is that Any should not cause any new errors (of course unless one
uses some --disallow-any-* flags).But in addition we should clarify the docs.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/python/mypy/issues/6701#issuecomment-485037387, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAWCWMRGXZKEQOYS4X2K65TPRJIVJANCNFSM4HHD5WBA
.>
--Guido (mobile)
I'd also like to add support for https://github.com/python/mypy/issues/6701#issuecomment-485037387 - and wanted to share a particular use case that may offer motivation.
I'm working on an interface for optional third party Spreadsheet reading applications. Conceptually a Spreadsheet is pretty well defined, but the various readers and file formats have different ways of describing them. In the Excel world this could be named a "Workbook" whereas the OpenDocument world may just refer to it as a "Document".
I think my base class would ideally look something like:
Spreadsheet_T = NewType('Spreadsheet_T', Any)
Sheet_T = NewType('Sheet_T', Any)
class SpreadsheetReader(ABC):
@property
@abstractmethod
def spreadsheet_cls(self) -> Type[Spreadsheet_T]:
...
@abstractmethod
def get_first_sheet(self, spreadsheet: Spreadsheet_T) -> Sheet_T:
...
So if I were interacting with openpyxl that subclass would look something like:
class OpenpyxlReader(SpreadsheetReader):
@property
def spreadsheet_cls(self) -> Type[Spreadsheet_T]:
from openpyxl import Workbook
return Workbook
def get_first_sheet(self, spreadsheet: Spreadsheet_T) -> Sheet_T:
return spreadsheet.worksheets[0]
Whereas something from the OpenDocument world would look as follows:
class OdfpyReader(SpreadsheetReader):
@property
def spreadsheet_cls(self) -> Type[Spreadsheet_T]:
from odf.opendocument import OpenDocument
return OpenDocument
def get_first_sheet(self, spreadsheet: Spreadsheet_T) -> Sheet_T:
from odf.table import Table
tables = self.book.getElementsByType(Table)
return tables[0]
This would obviously only be used for nominal typing but since these are optional third party dependencies for which I am only defining an interface I can't use that anyway.
Here is another vote for allowing a NewType from Any - with the reality of many libraries still lacking type stubs, allowing me to NewType their classes (which mypy thinks are Any) is a basic sort of safety feature that would really help me. Is there any chance of this happening? Or any workaround that anyone has discovered?
I think I found a workaround:
import typing as t
class AWSClient:
def __getattr__(self, item: str) -> t.Any:
pass
SQS = t.NewType('SQS', AWSClient)
S3 = t.NewType('S3', AWSClient)
Most helpful comment
Here is another vote for allowing a NewType from Any - with the reality of many libraries still lacking type stubs, allowing me to NewType their classes (which mypy thinks are Any) is a basic sort of safety feature that would really help me. Is there any chance of this happening? Or any workaround that anyone has discovered?