Skip to content

Instantly share code, notes, and snippets.

@gidgid
gidgid / ambiguous_type_coercion.py
Last active November 20, 2020 14:00
Ambiguity when using type coercion
from pydantic import BaseModel, PositiveInt
class UserResponse(BaseModel):
user_input: bool # 1
def test_what_did_the_user_mean():
assert UserResponse(user_input='yes').user_input is True # 2
@gidgid
gidgid / pydantic_strict_types_example.py
Last active October 4, 2020 14:04
Pydantic strict types prevent type coercion
import pytest
from pydantic import BaseModel, ValidationError, StrictInt, StrictBool
class UserResponse(BaseModel):
user_input: StrictBool # 1
def test_only_bool_responses_are_accepted():
assert UserResponse(user_input=True).user_input is True # 2
@gidgid
gidgid / none_key_value_pairs.py
Created October 4, 2020 14:16
Models that are not made of key-value pairs
import pytest
from typing import List
from pydantic import BaseModel
class Names(BaseModel):
values: List[str]
def test_values_is_not_part_of_the_input_data():
@gidgid
gidgid / multi_params.py
Created October 9, 2020 10:53
Function that requires multiple parameters
def crawl_page(url, output_file, num_retries): # 1
"""
Implementation omitted for the sake of brevity
"""
crawl_page(
url="http://hopefully.doesnt.exi.st", output_file="page_content.csv", num_retries=4
)
@gidgid
gidgid / passing_dict_as_a_function_parameter.py
Last active October 9, 2020 10:58
More function parameters usually require a dict to pass them
def crawl_page(url, crawl_request):
output_file = crawl_request["output_file"] # 1
num_retries = crawl_request["num_retries"] # 1
is_polite = crawl_request["is_polite"] # 1
follow_redirects = crawl_request["follow_redirects"] # 1
# rest of the implementation excluded for the sake of brevity
crawl_request = {
"output_file": "page_content.csv",
@gidgid
gidgid / type_hints_on_some_dicts.py
Last active October 11, 2020 06:03
type hints only works on some dictionaries
from typing import Dict
ids_to_names: Dict[str, str] = {
"1234": "John",
"2345": "Doe",
"3456": "Alice",
"4567": "Bob",
} # 1
@gidgid
gidgid / models_should_be_unique.py
Last active November 7, 2020 19:24
Same keys and values cause dicts to be equal but data classes are still different
from dataclasses import dataclass
def test_given_dicts_with_the_same_keys_values_then_they_are_equal():
user = {"name": "John", "lastname": "Doe", "age": 42}
employee = {"name": "John", "lastname": "Doe", "age": 42}
assert user == employee, "Ideally, these would be different"
@gidgid
gidgid / parse_vs_validation.py
Created October 27, 2020 21:44
Comparing parsing to validation
from dataclasses import dataclass
from typing import List
import pytest
# User's name != '' and age > 0 and hobbies > []
# and a none empty list of hobbies
# example: {'name': 'John', 'age': 30, hobbies: ['Rock Climbing', 'Books']}
@gidgid
gidgid / comparing_parsing_to_validation.py
Last active October 29, 2020 07:09
The functions signatures already show the difference between these 2 approaches
from dataclasses import dataclass
from typing import List
# Users have:
# a name which is a non-empty string
# an age which is a positive int
# at least one hobbie (which is a non empty list)
@dataclass
@gidgid
gidgid / data_class_with_properties.py
Last active November 7, 2020 19:39
Properties are a great way to abstract over an internal structure
from typing import List, Set
import attr
@attr.s(auto_attribs=True)
class Employee:
name: str
age: int
hobbies: List[dict] # 1