drf-spectacular μμ query paramμ μ΄μ©ν version λ³ api νκΈ°
API κ°λ° νλ€λ³΄λ©΄ νμνΈνμ±μ μ§ν€κΈ° μν΄ versioning μ ν΄μΌν λκ° μλ€. drf μμλ μ¬λ¬κ°μ§ versioning λ°©λ²μ μ 곡 μ€μΈλ°, swagger url μ μ€μ νκΈ° λ²κ±°λ‘λ€. λλ¬Έμ drf μμλ μνλ versioning μ μ μνκ³ swagger μμλ QueryParameterVersioning μΌλ‘ μ κ·Ό κ°λ₯ν λ°©λ²μ μκ°νλ€. drf setting REST_FRAMEWORK = { ... "DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning", "DEFAULT_VERSION": "1", "ALLOWED_VERSIONS": ["1", "2"], } μμ μμλ drf μμλ accept header λ₯Ό μ΄μ©ν versioning μ μ¬μ©νλ€. κ·Έ μΈλ λ¬Έμ μ°Έμ‘° drf-spectacular url μ μ λ° setting from rest_framework.versioning import QueryParameterVersioning urlpatterns += [ ... path('schema/', SpectacularAPIView.as_view(versioning_class=QueryParameterVersioning), name='schema'), path('schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='api:schema'), name='swagger-ui'), path('schema/redoc/', SpectacularRedocView.as_view(url_name='api:schema'), name='redoc'), ] swagger-ui νμ΄μ§κ° query paramμ μν΄ version μ λ³κ²½ν μ μλλ‘ view μ versioning_class λ₯Ό QueryParameterVersioning μΌλ‘ μ μνλ€. ...
default value parameter κ° κ°λ μ±μ λ―ΈμΉλ ν΄μ
default value parameter λ ν¨μμ νλΌλ―Έν°λ₯Ό μ§μ ν λ μμ£Ό μ°μ΄λ λ°©λ²μ΄λ€. def foo(a: bool = True): if a: return "foo" else: return "bar" λ¬Έμ λ μ΄ λ°©λ²μ΄ ν¨μμ μ μμμ κ²½μ°μλ λͺ μμ μΌλ‘ λκ»΄μ§μ§λ§ μ¬μ©μ νΉμ λ μμ κ²½μ°μλ κ΅μ₯ν 묡μμ μ΄λΌλλ° μλ€. # default argument >> foo() "foo" # positional argument >> foo(True) "foo" # keyword argument >> foo(a=False) "bar" default value parameter λ positional / keyword argument μΈμλ νλμ λ°©λ²μ λ λλ €μ£Όλλ°, λͺ μμ μΌλ‘ argument λ₯Ό λκΈ°μ§ μμλ μ΄λ―Έ μ§μ λ default value λ₯Ό ν¨μ λ΄μμ μ¬μ©ν μ μκ² λ νλ€. ...
Mixin class μ¬μ©μ app κ° κ³μΈ΅ ꡬ쑰
μμ ν¬μ€ν ν circular import μ λν μκ° μμ ν΄λΉ λ¬Έμ κ° λ°μν κ²½μ°, κ³μΈ΅ ꡬ쑰λ₯Ό λ¨Όμ μκ°ν΄λ³΄μλ μ΄μΌκΈ°λ₯Ό νμλ€. μ΄λ²μλ μ΄μ΄μ class μ 곡ν΅λ κΈ°λ₯μ λ½μλΌ λ κ³μΈ΅ ꡬ쑰λ₯Ό μ μ‘κΈ° μν λ°©λ²μ μκ°ν΄λ³΄μλ€. μΌλ°μ μΌλ‘ Mixin class λ νμ ν΄λμ€λ€μ 곡ν΅μ λ¬Άμ΄ μμ abstract λ‘ λ½λλ° μ¬μ©λλ, κ°λμ μμ ν΄λμ€λ€μ 곡ν΅λ κΈ°λ₯μ λΆμ΄λ μ©λλ‘λ μ¬μ©λλ€. django λ‘ κ°μ νκ³ μμλ₯Ό λ λ€. # A app class A(models.Model): nickname = models.CharField(...) def validate_nickname(self): ... # B app class B(models.Model): nickname = models.CharField(...) def validate_nickname(self): ... μ΄λ κ² κ³΅ν΅λ field μ methodκ° μλ κ²½μ°, ννΈνλ₯Ό λ§κΈ° μν΄ abstract model μ μ΄μ©νμ¬ μμμ abstract class λ₯Ό λ§λ λ€. ...
Python λ΄λΆμ C μ½λ λ€μ¬λ€λ³΄κΈ°
! μλμ μμ λ λͺ¨λ macOS Monterey 12.5.1 μμ μμ±λμλ€. λ¨Όμ python λ΄λΆμ c μ½λλ₯Ό λ€μ¬λ€λ³΄κΈ° μν΄μλ cpython μμ€λ₯Ό λ°μμΌ νλ€. git clone https://github.com/python/cpython cd cpython μνλ λ²μ μΌλ‘ branch λ₯Ό λ°κΏμ£Όκ³ μ»΄νμΌμ μ§ννλ€. configure μ΅μ μ°Έκ³ git switch 3.9 ./configure --with-pydebug --with-openssl=$(brew --prefix openssl) make -s -j2 make μ macOS μμ 'lzma.h' file not found κ° λ°μν κ²½μ° brew λ‘ xz λ₯Ό μ€μΉνκ³ νκ²½λ³μλ₯Ό μ‘μμ€λ€. νκ²½λ§λ€ pathκ° λ€λ₯Όμ μμμ μ£Όμ ...
PEP 3119 ABC λ²μ
PEP 3119 β Introducing Abstract Base Classes original link μ΄λ‘ μ ν΄μ κ°μ²΄ μ§ν₯ νλ‘κ·Έλλ°μμ, κ°μ²΄μ μνΈμμ©νλ μ¬μ© ν¨ν΄μ λκ°μ§ κΈ°λ³Έ λΆλ₯λ‘ λλ μ μλ€. νλλ βνΈμΆ(invocation)β μ΄κ³ λ€λ₯Έ νλλ βλΆμ(inspection)β μ΄λ€. νΈμΆμ κ°μ²΄μ λ©μλλ₯Ό νΈμΆνλ κ²μ μλ―Ένλ€. λκ° λ€νμ±κ³Ό κ²°ν©λμ΄ λ©μλλ₯Ό νΈμΆνλ©΄ μ΄λ€ νμ μ κ°μ²΄μ΄λμ λ°λΌ λ€λ₯Έ μ½λλ₯Ό μ€ννκ² λλ€. class A: def foo(self): print("A") class B(A): def foo(self): print("B") A().foo() B().foo() λΆμμ μΈλΆ μ½λ(ν΄λΉ κ°μ²΄μ λ©μλ λ°μ)μμ ν΄λΉ κ°μ²΄μ νμ μ΄λ νλ‘νΌν°λ₯Ό νμΈνκ³ νμΈν μ 보μ λ°λΌ μ΄λ»κ² κ°μ²΄λ₯Ό λ€λ£°μ§ κ²°μ νλ κ²μ μλ―Ένλ€. ...
Circular importμ λν μκ°
μΈν°λ·μ 보면 λ§μ circular import λ¬Έμ ν΄κ²° λ°©λ²μ μ°Ύμ μ μλ€. λνμ μΈ ν΄κ²°λ°©λ². def foo(): import smth ... μμ κ°μ΄ ν¨μ λ΄λΆμμ import λ₯Ό νλ€λ©΄ ννΌκ° κ°λ₯νλ€. νλ‘κ·Έλ¨μ λ¬Έμ μμ΄ λμνκΈ° μμνκ³ , μ΄ν μ΄ λ¬Έμ λ κ·Έλλ‘ μνμ§λ€. μ΄κ² μ³μ λ°©λ²μΌκΉ? μΌλ¨ ν΄λΉ λ¬Έμ κ° μ λ°μνλ μ§λΆν° μκ°ν΄λ³΄μ. # foo.py import bar ... # bar.py import foo ... μ΄λ κ² μλ‘λ₯Ό import νλ κ²½μ° λ°μνλ€. κ°λ°μ νλ€λ³΄λ©΄ ννκ² λ°μνλ κ²½μ°μΈλ°, λ¨μν μμ μκ°ν λ°©λ²μΌλ‘ ννΌνλ κ²λ§ κ³ λ €νμ¬ μμ¬μμ΄ μλ€. ...
Early returnμ λν μκ°
early return μ΄λ νΉμ μν©μμ function λ΄ μ£Όμ λ‘μ§μ΄ μ€νλκΈ° μ΄μ μ returnμ ν¨μΌλ‘μ¨ μ€ν costλ₯Ό μ€μ΄κ³ κ°λ μ±μ λμ΄λ λ°©λ²μ΄λ€. def notify(data): if not data.get("to"): return False if data.get("platform") not in NOTIFY_PLATFORMS: return False return NOTIFY_PLATFORMS[data["platform"]](data) μμ κ²½μ°μμ 보λ―μ΄ μλ¦Όμ μ£Όλ functionμμ μ μ²λ¦¬λ₯Ό ν΅ν΄ μ€μ λ‘μ§μ΄ μ€ν λκΈ° μ΄μ μ returnμ μ£Όλ κ²μ μ μ μλ€. μμ’μ μλ‘ λ³΄λ©΄ def notify(data): if not data.get("to"): return False elif data.get("platform") not in NOTIFY_PLATFORMS: return False else: return NOTIFY_PLATFORMS[data["platform"]](data) μ κ°μ΄ if-elif-else λ‘ λͺ¨λ λ‘μ§μ κ°μΈλ κ²½μ°λΌκ³ μκ° λλλ°, μ΄ κ²½μ°λ ν΄λΉ functionμ μ μ λ‘μ§μ΄ μ΄λ λΆκΈ°μΈμ§ μκΈ° νλ€λ€. ...