Skip to content

Commit

Permalink
Adding support for addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
whubsch committed Aug 1, 2024
1 parent 52ab656 commit 3ad7453
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 26 deletions.
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Framework :: Hatch",
"License :: OSI Approved :: MIT License",
"Typing :: Typed",
]
Expand Down
29 changes: 29 additions & 0 deletions src/overturetoosm/addresses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import Dict, Literal
from .objects import AddressProps


def process_address(
props: dict,
style: Literal["US"] = "US",
) -> Dict[str, str]:
"""Convert Overture's address properties to OSM tags.
Args:
props (dict): The feature properties from the Overture GeoJSON.
style (str, optional): How to handle the `address_levels` field. Open a pull request or issue to add support for other regions. Defaults to "US".
Returns:
Dict[str, str]: The reshaped and converted properties in OSM's flat str:str schema.
"""
bad_tags = ["version", "theme", "type", "address_levels"]
print(props)
prop = AddressProps(**props)
obj_dict = prop.model_dump(exclude_none=True, by_alias=True)
if prop.address_levels:
if style == "US":
obj_dict["addr:state"] = prop.address_levels[0]["value"]

for tag in bad_tags:
obj_dict.pop(tag, None)

return obj_dict
63 changes: 46 additions & 17 deletions src/overturetoosm/objects.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,78 @@
"""Pydantic models needed throughout the project."""

from typing import Dict, List, Optional
import pydantic
from pydantic import AnyUrl, BaseModel, Field


class Sources(pydantic.BaseModel):
class Sources(BaseModel):
"""Overture sources model."""

property: str
dataset: str
record_id: Optional[str] = None
confidence: float = pydantic.Field(default=0.0)
confidence: float = Field(default=0.0)
update_time: Optional[str] = None


class Names(pydantic.BaseModel):
class Names(BaseModel):
"""Overture names model."""

primary: str
common: Optional[Dict[str, str]]
rules: Optional[List[Dict[str, str]]]


class Addresses(pydantic.BaseModel):
class Address(BaseModel):
"""Overture addresses model."""

freeform: Optional[str]
locality: Optional[str]
postcode: Optional[str]
region: Optional[str]
country: Optional[str]
country: Optional[str] = Field(pattern=r"^[A-Z]{2}$")


class Categories(pydantic.BaseModel):
class Categories(BaseModel):
"""Overture categories model."""

main: str
alternate: Optional[List[str]]


class Brand(pydantic.BaseModel):
class Brand(BaseModel):
"""Overture brand model."""

wikidata: Optional[str]
wikidata: Optional[str] = Field(pattern=r"Q[0-9]+")
names: Names


class PlaceProps(pydantic.BaseModel):
class OvertureBase(BaseModel):
"""Overture base model."""

theme: str
type: str
version: int


class PlaceProps(BaseModel):
"""Overture properties model.
Use this model directly if you want to manipulate the `place` properties yourself.
"""

id: str
id: Optional[str] = None
version: int
update_time: str
sources: List[Sources]
names: Names
brand: Optional[Brand] = None
categories: Optional[Categories] = None
confidence: float = pydantic.Field(ge=0.0, le=1.0)
websites: Optional[List[str]] = None
socials: Optional[List[str]] = None
confidence: float = Field(ge=0.0, le=1.0)
websites: Optional[List[AnyUrl]] = None
socials: Optional[List[AnyUrl]] = None
emails: Optional[List[str]] = None
phones: Optional[List[str]] = None
addresses: List[Addresses]
addresses: List[Address]


class ConfidenceError(Exception):
Expand Down Expand Up @@ -126,14 +136,14 @@ def __str__(self) -> str:
return f"{self.message} {{category={self.category}}}"


class BuildingProps(pydantic.BaseModel):
class BuildingProps(BaseModel):
"""Overture building properties.
Use this model directly if you want to manipulate the `building` properties yourself.
"""

version: int
class_: str = pydantic.Field(alias="class")
class_: str = Field(alias="class")
subtype: str
sources: List[Sources]
height: Optional[float] = None
Expand All @@ -150,3 +160,22 @@ class BuildingProps(pydantic.BaseModel):
roof_orientation: Optional[str] = None
roof_color: Optional[str] = None
roof_height: Optional[float] = None


class AddressLevel(BaseModel):
"""Overture address level model."""

value: str


class AddressProps(OvertureBase):
"""Overture address properties.
Use this model directly if you want to manipulate the `address` properties yourself.
"""

number: Optional[str] = Field(serialization_alias="addr:housenumber")
street: Optional[str] = Field(serialization_alias="addr:street")
postcode: Optional[str] = Field(serialization_alias="addr:postcode")
country: Optional[str] = Field(serialization_alias="addr:country")
address_levels: Optional[List[AddressLevel]] = None
4 changes: 2 additions & 2 deletions src/overturetoosm/places.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ def process_place(

if prop_obj.socials is not None:
for social in prop_obj.socials:
if "facebook" in social:
if "facebook" in str(social):
new_props["contact:facebook"] = social
elif "twitter" in social:
elif "twitter" in str(social):
new_props["contact:twitter"] = social

if prop_obj.brand:
Expand Down
12 changes: 6 additions & 6 deletions tests/test_places.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ def clean_fix() -> Dict[str, Any]:
"addr:city": "City",
"addr:postcode": "12345",
"addr:state": "CA",
"addr:country": "Country",
"addr:country": "US",
"phone": "+1234567890",
"website": "https://example.com",
"source": "dataset1 via overturetoosm",
"office": "lawyer",
"lawyer": "notary",
"contact:facebook": "www.facebook.com/example",
"contact:facebook": "https://www.facebook.com/example",
}


Expand Down Expand Up @@ -72,15 +72,15 @@ def geojson_fix() -> Dict[str, Any]:
},
"confidence": 0.8,
"websites": ["https://example.com"],
"socials": ["www.facebook.com/example"],
"socials": ["https://www.facebook.com/example"],
"phones": ["+1234567890"],
"addresses": [
{
"freeform": "123 Main St",
"locality": "City",
"postcode": "12345",
"region": "CA",
"country": "Country",
"country": "US",
}
],
},
Expand Down Expand Up @@ -123,15 +123,15 @@ def props_fix() -> Dict[str, Any]:
},
"confidence": 0.8,
"websites": ["https://example.com"],
"socials": ["www.facebook.com/example"],
"socials": ["https://www.facebook.com/example"],
"phones": ["+1234567890"],
"addresses": [
{
"freeform": "123 Main St",
"locality": "City",
"postcode": "12345",
"region": "CA",
"country": "Country",
"country": "US",
}
],
}
Expand Down

0 comments on commit 3ad7453

Please sign in to comment.