from dataclasses import dataclass, field
from typing import Dict
@dataclass
class Speaker:
name: str
github: str
twitter: str
experience: Dict[str, int] = field(default_factory=dict)
def knows(self, **languages: int) -> None:
self.experience.update(**languages)
@property
def github_url(self) -> str:
return f'https://github.com/{self.github}'
@property
def twitter_url(self) -> str:
return f'https://twitter.com/{self.twitter}'
igor = Speaker('Igor Davydenko', 'playpauseandstop', 'playpausenstop')
igor.knows(python=2007, javascript=2011)
from typing import List, Optional
@dataclass
class Topic:
name: str
description: Optional[str]
@dataclass
class Agenda:
topics: List[Topic]
pycon_de_2018 = Agenda([
Topic('Maintainability'),
Topic('Predictability'),
Topic('Developer Experience'),
Topic('Toolset'),
])
def generate_token(email, expired_at, secret_key):
"""Generate valid JWT token for given email."""
encoded = jwt.encode({'email': email, 'exp': expired_at}, secret_key)
return encoded.decode('utf-8')
def generate_token(email: str, expired_at: float, secret_key: bytes) -> str:
"""Generate valid JWT token for given email."""
encoded = jwt.encode({'email': email, 'exp': expired_at}, secret_key)
return encoded.decode('utf-8')
core
/ myproject
*.pyi
)
py.typed
file to each typed packagepy.typed
(and stubs) files
as package_data
Examples: rororo, aiohttp-middlewares
typeshed
and friendsrequests
, jinja
, etc)
And validating data doesn't fix the problem
async def add_project(request):
valid_data = validate_add_project(await request.json())
async with request.app['db'].acquire() as conn:
await conn.execute(
projects_table
.insert()
.values(
name=valid_data['nam'],
description=valid_data['description'],
)
)
return web.json_response(status=201)
KeyError
AttributeError
from typing import NamedTuple
class AddProjectStruct(NamedTuple):
name: str
description: Optional[str] = None
...
def validate_add_project(data: Dict[str, str]) -> AddProjectStruct:
...
from mypy_extensions import TypedDict
AddProjectDict = TypedDict('AddProject', {
'name': str,
'description': Optional[str],
})
from dataclasses import dataclass
@dataclass
class AddProjectData:
name: str
description: Optional[str] = None
from pydantic.dataclasses import dataclass
@dataclass
class AddProjectData:
name: str
description: Optional[str] = None
...
async def add_project(request: web.Request) -> web.Response:
data = AddProjectData(**await request.json())
...
Any
datadef build_secret(email: str, secret_key: bytes) -> str:
...
def generate_otp(email: str,
period: int,
secret_key: bytes) -> Tuple[int, float]:
...
def generate_token(email: str, expired_at: float, secret_key: bytes) -> str:
...
def send_email(app: web.Application, email: str) -> float:
...
def validate_otp(app: web.Application,
otp: int,
email: str,
timestamp: float) -> bool:
...
def validate_token(app: web.Application,
token: str) -> Tuple[bool, Optional[Mapping[str, Any]]]:
...
Fact: Your start typing much faster with annotated code
mypy
allows you to find additional problems with
your code
fn add(x: i32, y: i32) -> i32 {
x + y
}
struct DebugWriter {
sha: Writer<Blake2b512>,
data: Opt<Vec<u8>>,
}
// @flow
const add = (x: number, y: number): number => x + y
type Props = {
id: number,
text: str,
topics: Array<str>
}
add : Int -> Int -> Int
add x y =
x + y
type alias TweetId =
Int
type alias Tweet =
{ id : TweetId
, text : String
, url : String
, createdAt : String
}
python -m mypy project/
dmypy
MonkeyType
is from InstagramPyAnnotate
is from DropboxBaseModel
for basic validation@dataclass
for better integration with mypyBaseSettings
for working with settingsmypy
authorsCython