# python/01-restful-api-design.py"""RESTful API design patterns and resource-based architecture"""fromtypingimportList,Dict,Any,Optional,Unionfromdataclassesimportdataclass,asdictfromenumimportEnumimportjsonfromdatetimeimportdatetimefromabcimportABC,abstractmethodclassHTTPMethod(Enum):"""HTTP methods"""GET="GET"POST="POST"PUT="PUT"PATCH="PATCH"DELETE="DELETE"classHTTPStatus(Enum):"""HTTP status codes"""OK=200CREATED=201NO_CONTENT=204BAD_REQUEST=400UNAUTHORIZED=401FORBIDDEN=403NOT_FOUND=404METHOD_NOT_ALLOWED=405CONFLICT=409UNPROCESSABLE_ENTITY=422INTERNAL_SERVER_ERROR=500@dataclassclassAPIResponse:"""Standard API response"""status_code:intdata:Optional[Any]=Nonemessage:Optional[str]=Noneerrors:Optional[List[str]]=Nonemetadata:Optional[Dict[str,Any]]=Nonedefto_dict(self)->Dict[str,Any]:"""Convert to dictionary"""response={"status_code":self.status_code,"success":200<=self.status_code<300}ifself.dataisnotNone:response["data"]=self.dataifself.message:response["message"]=self.messageifself.errors:response["errors"]=self.errorsifself.metadata:response["metadata"]=self.metadatareturnresponse@dataclassclassPaginationInfo:"""Pagination information"""page:intper_page:inttotal:inttotal_pages:inthas_next:boolhas_prev:booldefto_dict(self)->Dict[str,Any]:"""Convert to dictionary"""return{"page":self.page,"per_page":self.per_page,"total":self.total,"total_pages":self.total_pages,"has_next":self.has_next,"has_prev":self.has_prev}classResource(ABC):"""Base resource class"""def__init__(self,resource_id:str,created_at:datetime=None,updated_at:datetime=None):self.id=resource_idself.created_at=created_atordatetime.utcnow()self.updated_at=updated_atordatetime.utcnow()@abstractmethoddefto_dict(self)->Dict[str,Any]:"""Convert resource to dictionary"""pass@classmethod@abstractmethoddeffrom_dict(cls,data:Dict[str,Any])->'Resource':"""Create resource from dictionary"""pass@dataclassclassUser(Resource):"""User resource"""name:stremail:stris_active:bool=Truedefto_dict(self)->Dict[str,Any]:"""Convert user to dictionary"""return{"id":self.id,"name":self.name,"email":self.email,"is_active":self.is_active,"created_at":self.created_at.isoformat(),"updated_at":self.updated_at.isoformat()}@classmethoddeffrom_dict(cls,data:Dict[str,Any])->'User':"""Create user from dictionary"""returncls(resource_id=data["id"],name=data["name"],email=data["email"],is_active=data.get("is_active",True),created_at=datetime.fromisoformat(data["created_at"]),updated_at=datetime.fromisoformat(data["updated_at"]))classAPIResource:"""API resource handler"""def__init__(self,resource_type:str):self.resource_type=resource_typeself.resources:Dict[str,Resource]={}self.next_id=1defcreate(self,data:Dict[str,Any])->APIResponse:"""Create resource"""try:# Validate required fieldsifnotdata.get("name"):returnAPIResponse(status_code=HTTPStatus.BAD_REQUEST.value,errors=["Name is required"])# Create resourceresource_id=str(self.next_id)self.next_id+=1ifself.resource_type=="user":resource=User(resource_id=resource_id,name=data["name"],email=data["email"],is_active=data.get("is_active",True))else:raiseValueError(f"Unknown resource type: {self.resource_type}")self.resources[resource_id]=resourcereturnAPIResponse(status_code=HTTPStatus.CREATED.value,data=resource.to_dict(),message=f"{self.resource_type.title()} created successfully")exceptExceptionase:returnAPIResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,errors=[str(e)])defget(self,resource_id:str)->APIResponse:"""Get resource by ID"""ifresource_idnotinself.resources:returnAPIResponse(status_code=HTTPStatus.NOT_FOUND.value,errors=[f"{self.resource_type.title()} not found"])resource=self.resources[resource_id]returnAPIResponse(status_code=HTTPStatus.OK.value,data=resource.to_dict())deflist(self,page:int=1,per_page:int=10)->APIResponse:"""List resources with pagination"""total=len(self.resources)total_pages=(total+per_page-1)//per_pagestart=(page-1)*per_pageend=start+per_pageresources=list(self.resources.values())[start:end]data=[resource.to_dict()forresourceinresources]pagination=PaginationInfo(page=page,per_page=per_page,total=total,total_pages=total_pages,has_next=page<total_pages,has_prev=page>1)returnAPIResponse(status_code=HTTPStatus.OK.value,data=data,metadata={"pagination":pagination.to_dict()})defupdate(self,resource_id:str,data:Dict[str,Any])->APIResponse:"""Update resource"""ifresource_idnotinself.resources:returnAPIResponse(status_code=HTTPStatus.NOT_FOUND.value,errors=[f"{self.resource_type.title()} not found"])try:resource=self.resources[resource_id]# Update fieldsif"name"indata:resource.name=data["name"]if"email"indata:resource.email=data["email"]if"is_active"indata:resource.is_active=data["is_active"]resource.updated_at=datetime.utcnow()returnAPIResponse(status_code=HTTPStatus.OK.value,data=resource.to_dict(),message=f"{self.resource_type.title()} updated successfully")exceptExceptionase:returnAPIResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,errors=[str(e)])defdelete(self,resource_id:str)->APIResponse:"""Delete resource"""ifresource_idnotinself.resources:returnAPIResponse(status_code=HTTPStatus.NOT_FOUND.value,errors=[f"{self.resource_type.title()} not found"])delself.resources[resource_id]returnAPIResponse(status_code=HTTPStatus.NO_CONTENT.value,message=f"{self.resource_type.title()} deleted successfully")# Usage examplesdefexample_restful_api():"""Example RESTful API usage"""# Create API resourceuser_api=APIResource("user")# Create usercreate_data={"name":"John Doe","email":"john@example.com","is_active":True}create_response=user_api.create(create_data)print(f"Create response: {create_response.to_dict()}")# Get useruser_id="1"get_response=user_api.get(user_id)print(f"Get response: {get_response.to_dict()}")# List userslist_response=user_api.list(page=1,per_page=10)print(f"List response: {list_response.to_dict()}")# Update userupdate_data={"name":"Jane Doe"}update_response=user_api.update(user_id,update_data)print(f"Update response: {update_response.to_dict()}")# Delete userdelete_response=user_api.delete(user_id)print(f"Delete response: {delete_response.to_dict()}")
# python/02-api-versioning.py"""API versioning strategies and implementation"""fromtypingimportList,Dict,Any,Optional,UnionfromdataclassesimportdataclassfromenumimportEnumimportrefromdatetimeimportdatetimeclassAPIVersion(Enum):"""API version enumeration"""V1="v1"V2="v2"V3="v3"@dataclassclassVersionInfo:"""API version information"""version:strrelease_date:datetimedeprecation_date:Optional[datetime]=Noneis_deprecated:bool=Falseis_sunset:bool=Falsesunset_date:Optional[datetime]=NoneclassAPIVersionManager:"""API version manager"""def__init__(self):self.versions:Dict[str,VersionInfo]={}self.current_version=APIVersion.V1.valueself.default_version=APIVersion.V1.valuedefregister_version(self,version:str,release_date:datetime,deprecation_date:Optional[datetime]=None,sunset_date:Optional[datetime]=None)->None:"""Register API version"""version_info=VersionInfo(version=version,release_date=release_date,deprecation_date=deprecation_date,is_deprecated=deprecation_dateisnotNone,sunset_date=sunset_date,is_sunset=sunset_dateisnotNone)self.versions[version]=version_infodefget_version_info(self,version:str)->Optional[VersionInfo]:"""Get version information"""returnself.versions.get(version)defis_version_supported(self,version:str)->bool:"""Check if version is supported"""version_info=self.get_version_info(version)ifnotversion_info:returnFalsereturnnotversion_info.is_sunsetdefget_supported_versions(self)->List[str]:"""Get list of supported versions"""return[versionforversion,infoinself.versions.items()ifnotinfo.is_sunset]defget_deprecated_versions(self)->List[str]:"""Get list of deprecated versions"""return[versionforversion,infoinself.versions.items()ifinfo.is_deprecatedandnotinfo.is_sunset]defget_sunset_versions(self)->List[str]:"""Get list of sunset versions"""return[versionforversion,infoinself.versions.items()ifinfo.is_sunset]classVersionedAPI:"""Versioned API implementation"""def__init__(self):self.version_manager=APIVersionManager()self.handlers:Dict[str,Dict[str,Any]]={}self.setup_versions()defsetup_versions(self)->None:"""Setup API versions"""# Register versionsself.version_manager.register_version("v1",datetime(2023,1,1),deprecation_date=datetime(2024,1,1))self.version_manager.register_version("v2",datetime(2023,6,1))self.version_manager.register_version("v3",datetime(2024,1,1))defregister_handler(self,version:str,endpoint:str,handler:Any)->None:"""Register versioned handler"""ifversionnotinself.handlers:self.handlers[version]={}self.handlers[version][endpoint]=handlerdefget_handler(self,version:str,endpoint:str)->Optional[Any]:"""Get versioned handler"""ifversionnotinself.handlers:returnNonereturnself.handlers[version].get(endpoint)defhandle_request(self,version:str,endpoint:str,method:str,data:Dict[str,Any])->Dict[str,Any]:"""Handle versioned request"""# Check if version is supportedifnotself.version_manager.is_version_supported(version):return{"error":"Unsupported API version","supported_versions":self.version_manager.get_supported_versions()}# Get handlerhandler=self.get_handler(version,endpoint)ifnothandler:return{"error":"Endpoint not found","version":version,"endpoint":endpoint}# Execute handlertry:result=handler(method,data)returnresultexceptExceptionase:return{"error":str(e),"version":version,"endpoint":endpoint}defget_version_headers(self,version:str)->Dict[str,str]:"""Get version-specific headers"""version_info=self.version_manager.get_version_info(version)ifnotversion_info:return{}headers={"API-Version":version,"API-Release-Date":version_info.release_date.isoformat()}ifversion_info.is_deprecated:headers["API-Deprecation-Date"]=version_info.deprecation_date.isoformat()headers["Warning"]=f"API version {version} is deprecated"ifversion_info.is_sunset:headers["API-Sunset-Date"]=version_info.sunset_date.isoformat()headers["Warning"]=f"API version {version} is sunset"returnheaders# Usage examplesdefexample_api_versioning():"""Example API versioning usage"""# Create versioned APIapi=VersionedAPI()# Register handlers for different versionsdefv1_user_handler(method:str,data:Dict[str,Any])->Dict[str,Any]:return{"version":"v1","method":method,"data":data}defv2_user_handler(method:str,data:Dict[str,Any])->Dict[str,Any]:return{"version":"v2","method":method,"data":data,"enhanced":True}api.register_handler("v1","users",v1_user_handler)api.register_handler("v2","users",v2_user_handler)# Handle requestsv1_response=api.handle_request("v1","users","GET",{})print(f"V1 response: {v1_response}")v2_response=api.handle_request("v2","users","GET",{})print(f"V2 response: {v2_response}")# Get version headersv1_headers=api.get_version_headers("v1")print(f"V1 headers: {v1_headers}")# Get supported versionssupported=api.version_manager.get_supported_versions()print(f"Supported versions: {supported}")
# python/04-api-error-handling.py"""API error handling and validation patterns"""fromtypingimportList,Dict,Any,Optional,UnionfromdataclassesimportdataclassfromenumimportEnumimportjsonfromdatetimeimportdatetimeclassAPIErrorCode(Enum):"""API error codes"""VALIDATION_ERROR="VALIDATION_ERROR"AUTHENTICATION_ERROR="AUTHENTICATION_ERROR"AUTHORIZATION_ERROR="AUTHORIZATION_ERROR"NOT_FOUND="NOT_FOUND"CONFLICT="CONFLICT"RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED"INTERNAL_SERVER_ERROR="INTERNAL_SERVER_ERROR"@dataclassclassAPIError:"""API error definition"""code:APIErrorCodemessage:strdetails:Optional[Dict[str,Any]]=Nonefield:Optional[str]=Nonedefto_dict(self)->Dict[str,Any]:"""Convert to dictionary"""error_dict={"code":self.code.value,"message":self.message}ifself.details:error_dict["details"]=self.detailsifself.field:error_dict["field"]=self.fieldreturnerror_dict@dataclassclassAPIErrorResponse:"""API error response"""status_code:interrors:List[APIError]request_id:Optional[str]=Nonetimestamp:datetime=Nonedef__post_init__(self):ifself.timestampisNone:self.timestamp=datetime.utcnow()defto_dict(self)->Dict[str,Any]:"""Convert to dictionary"""response={"status_code":self.status_code,"success":False,"errors":[error.to_dict()forerrorinself.errors],"timestamp":self.timestamp.isoformat()}ifself.request_id:response["request_id"]=self.request_idreturnresponseclassAPIValidator:"""API request validator"""def__init__(self):self.validators:Dict[str,callable]={}self.setup_validators()defsetup_validators(self)->None:"""Setup validators"""self.validators={"required":self._validate_required,"email":self._validate_email,"min_length":self._validate_min_length,"max_length":self._validate_max_length,"min_value":self._validate_min_value,"max_value":self._validate_max_value,"pattern":self._validate_pattern}defvalidate(self,data:Dict[str,Any],rules:Dict[str,Dict[str,Any]])->List[APIError]:"""Validate data against rules"""errors=[]forfield,field_rulesinrules.items():value=data.get(field)forrule_name,rule_valueinfield_rules.items():ifrule_nameinself.validators:error=self.validators[rule_name](field,value,rule_value)iferror:errors.append(error)returnerrorsdef_validate_required(self,field:str,value:Any,required:bool)->Optional[APIError]:"""Validate required field"""ifrequiredand(valueisNoneorvalue==""):returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' is required",field=field)returnNonedef_validate_email(self,field:str,value:Any,is_email:bool)->Optional[APIError]:"""Validate email format"""ifis_emailandvalueand"@"notinstr(value):returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' must be a valid email",field=field)returnNonedef_validate_min_length(self,field:str,value:Any,min_length:int)->Optional[APIError]:"""Validate minimum length"""ifvalueandlen(str(value))<min_length:returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' must be at least {min_length} characters",field=field)returnNonedef_validate_max_length(self,field:str,value:Any,max_length:int)->Optional[APIError]:"""Validate maximum length"""ifvalueandlen(str(value))>max_length:returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' must be at most {max_length} characters",field=field)returnNonedef_validate_min_value(self,field:str,value:Any,min_value:Union[int,float])->Optional[APIError]:"""Validate minimum value"""ifvalueisnotNoneandvalue<min_value:returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' must be at least {min_value}",field=field)returnNonedef_validate_max_value(self,field:str,value:Any,max_value:Union[int,float])->Optional[APIError]:"""Validate maximum value"""ifvalueisnotNoneandvalue>max_value:returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' must be at most {max_value}",field=field)returnNonedef_validate_pattern(self,field:str,value:Any,pattern:str)->Optional[APIError]:"""Validate pattern"""ifvalueandnotre.match(pattern,str(value)):returnAPIError(code=APIErrorCode.VALIDATION_ERROR,message=f"Field '{field}' does not match required pattern",field=field)returnNoneclassAPIErrorHandler:"""API error handler"""def__init__(self):self.validator=APIValidator()defhandle_validation_error(self,errors:List[APIError])->APIErrorResponse:"""Handle validation errors"""returnAPIErrorResponse(status_code=400,errors=errors)defhandle_authentication_error(self,message:str="Authentication required")->APIErrorResponse:"""Handle authentication errors"""returnAPIErrorResponse(status_code=401,errors=[APIError(code=APIErrorCode.AUTHENTICATION_ERROR,message=message)])defhandle_authorization_error(self,message:str="Insufficient permissions")->APIErrorResponse:"""Handle authorization errors"""returnAPIErrorResponse(status_code=403,errors=[APIError(code=APIErrorCode.AUTHORIZATION_ERROR,message=message)])defhandle_not_found_error(self,resource:str="Resource")->APIErrorResponse:"""Handle not found errors"""returnAPIErrorResponse(status_code=404,errors=[APIError(code=APIErrorCode.NOT_FOUND,message=f"{resource} not found")])defhandle_conflict_error(self,message:str="Resource conflict")->APIErrorResponse:"""Handle conflict errors"""returnAPIErrorResponse(status_code=409,errors=[APIError(code=APIErrorCode.CONFLICT,message=message)])defhandle_internal_error(self,message:str="Internal server error")->APIErrorResponse:"""Handle internal errors"""returnAPIErrorResponse(status_code=500,errors=[APIError(code=APIErrorCode.INTERNAL_SERVER_ERROR,message=message)])# Usage examplesdefexample_api_error_handling():"""Example API error handling usage"""# Create error handlererror_handler=APIErrorHandler()# Create validatorvalidator=APIValidator()# Validate datadata={"name":"","email":"invalid-email"}rules={"name":{"required":True,"min_length":2},"email":{"required":True,"email":True}}errors=validator.validate(data,rules)iferrors:error_response=error_handler.handle_validation_error(errors)print(f"Validation error: {error_response.to_dict()}")# Handle different error typesauth_error=error_handler.handle_authentication_error()print(f"Auth error: {auth_error.to_dict()}")not_found_error=error_handler.handle_not_found_error("User")print(f"Not found error: {not_found_error.to_dict()}")