Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 561 – 타입 정보의 배포와 패키징

Author:
Emma Harper Smith <emma at python.org>
Status:
Final
Type:
Standards Track
Topic:
Packaging, Typing
Created:
09-Sep-2017
Python-Version:
3.7
Post-History:
10-Sep-2017, 12-Sep-2017, 06-Oct-2017, 26-Oct-2017, 12-Apr-2018

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

Important

This PEP is a historical document: see Type information in libraries for up-to-date specs and documentation. Canonical typing specs are maintained at the typing specs site; runtime typing behaviour is described in the CPython documentation.

×

See the typing specification update process for how to propose changes to the typing spec.

초록

PEP 484는 타이핑을 점진적으로 적용하고 쉽게 도입할 수 있도록 한다는 목표로 Python에 타입 힌트를 도입했습니다. 현재 타이핑 정보는 수동으로 배포해야 합니다. 이 PEP는 최소한의 작업으로 기존 도구를 활용하여 타입 정보를 패키지로 만들고 배포하는 표준화된 방법과, 타입 검사기가 모듈을 해석하고 타입 검사를 위해 이 정보를 수집하는 순서를 제공합니다.

근거

현재 패키지 작성자들은 인라인 타입 정보가 포함된 코드를 배포하기를 원합니다. 또한 유지 관리자들은 새로운 어노테이션 문법을 사용하면서도 Python 2 호환성을 유지하기 위해 스텁 파일을 배포하기를 원합니다. 그러나 타입 정보를 포함한 패키지를 배포하는 표준 방법은 없습니다. 또한 스텁 파일을 비공개로 제공하려는 경우 사용할 수 있는 유일한 방법은 MYPYPATH 또는 그에 상응하는 설정을 통해 스텁을 수동으로 가리키는 것입니다. 패키지를 공개적으로 릴리스할 수 있다면 typeshed [1]에 추가할 수 있습니다. 그러나 이 방법은 확장성이 없으며 typeshed 유지 관리자들에게 부담이 됩니다. 게다가 스텁의 버그 수정이 typeshed를 사용하는 도구의 릴리스에 묶이게 됩니다.

PEP 484에는 타이핑 정보 배포에 관한 짧은 절이 있습니다. 이 절에서 PEP는 스텁 파일을 제공할 때 shared/typehints/pythonX.Y/를 사용할 것을 권장합니다. 그러나 각 서드파티 라이브러리마다 스텁 파일의 경로를 수동으로 추가하는 방식은 확장성이 없습니다. 사람들이 택한 가장 간단한 방법은 MYPYPATH에 site-packages를 추가하는 것이지만, 이렇게 하면 매우 동적인 패키지(예: sqlalchemy와 Django)에서 타입 검사기가 실패하게 됩니다.

용어 정의

“MAY”, “MUST”, “SHOULD”, “SHOULD NOT”의 정의는 RFC 2119에 기술된 대로 해석해야 합니다.

“인라인(inline)” - 타입이 PEP 526 및 PEP 3107 문법을 사용하여 런타임 코드의 일부로 포함된 것입니다(파일 이름이 .py로 끝납니다).

“스텁(stubs)” - 런타임 코드 없이 타입 정보만 담고 있는 파일입니다(파일 이름이 .pyi로 끝납니다).

“배포물(Distributions)”은 릴리스를 게시하고 배포하는 데 사용되는 패키징된 파일입니다. (PEP 426)

“모듈(Module)”은 Python 런타임 코드 또는 스텁 형태의 타입 정보를 담고 있는 파일입니다.

“패키지(Package)”는 Python 모듈에 네임스페이스를 부여하는 하나 이상의 디렉터리입니다. (패키지와 배포물의 차이에 유의하십시오. 대부분의 배포물은 자신이 설치하는 하나의 패키지 이름을 따서 명명되지만, 일부 배포물은 여러 패키지를 설치합니다.)

명세

패키지에서 타이핑을 지원하는 데에는 여러 가지 동기와 방법이 있습니다. 이 PEP는 타이핑 사용자가 만들고자 하는 패키지를 다음 세 가지 유형으로 구분합니다:

  1. 패키지 유지 관리자가 타입 정보를 인라인으로 추가하려는 경우입니다.
  2. 패키지 유지 관리자가 스텁을 통해 타입 정보를 추가하려는 경우입니다.
  3. 서드파티나 패키지 유지 관리자가 패키지의 스텁 파일을 공유하고 싶지만, 유지 관리자는 이를 패키지의 소스에 포함하고 싶어 하지 않는 경우입니다.

이 PEP는 세 가지 시나리오를 모두 지원하고, 이를 패키징과 배포에 간단히 추가할 수 있도록 하는 것을 목표로 합니다.

이 명세의 두 가지 주요 부분은 패키징 명세와 모듈 타입 정보를 해석하는 해석 순서입니다. 타입 검사 명세는 shared/typehints/pythonX.Y/ PEP 484의 명세를 대체하기 위한 것입니다.

새로운 서드파티 스텁 라이브러리는 typeshed에 추가되는 대신 이 PEP에서 제안하는 서드파티 패키징 방법을 통해 스텁을 배포해야 합니다(SHOULD). Typeshed는 계속 사용되지만, 유지 관리자를 찾게 되면 typeshed에 있는 서드파티 스텁을 별도의 패키지로 분리할 수 있습니다(MAY).

타입 정보 패키징

타입 정보의 패키징과 배포를 최대한 간단하고 쉽게 하기 위해, 패키징과 배포는 기존 프레임워크를 통해 이루어집니다.

자신의 코드에 대한 타입 검사를 지원하려는 패키지 유지 관리자는 타입을 지원하는 패키지에 py.typed라는 이름의 마커 파일을 반드시 추가해야 합니다(MUST). 이 마커는 재귀적으로 적용됩니다. 최상위 패키지에 이 마커가 포함되어 있으면 그 하위 패키지도 모두 반드시 타입 검사를 지원해야 합니다(MUST). 이 파일이 패키지와 함께 설치되도록 하려면, 유지 관리자는 아래에 나온 distutils의 package_data 같은 기존 패키징 옵션을 사용할 수 있습니다.

Distutils 옵션 예시:

setup(
    ...,
    package_data = {
        'foopkg': ['py.typed'],
    },
    ...,
    )

네임스페이스 패키지(PEP 420 참고)의 경우, 충돌을 피하고 명확성을 높이기 위해 py.typed 파일을 네임스페이스의 하위 모듈에 두어야 합니다.

이 PEP는 모듈만 있는 배포나 네임스페이스 패키지 안의 단일 파일 모듈의 일부로 타이핑 정보를 배포하는 것을 지원하지 않습니다.

단일 파일 모듈은 패키지로 리팩터링하고, 위에서 설명한 대로 해당 패키지가 타이핑을 지원한다고 표시해야 합니다.

스텁 전용 패키지

모든 타입 정보를 담은 스텁 파일을 함께 배포하려는 패키지 유지 관리자의 경우, *.pyi 스텁을 대응하는 *.py 파일 옆에 두는 것이 권장됩니다. 하지만 스텁을 별도의 패키지에 넣어 따로 배포할 수도 있습니다. 스텁 파일을 배포하려는 서드파티에게도 이 방법이 유용할 수 있습니다. foopkg라는 이름의 패키지에 대한 타입 스텁의 경우, 스텁 패키지의 이름은 반드시 foopkg-stubs 형식을 따라야 합니다(MUST). 스텁 전용 패키지에는 py.typed 마커를 추가할 필요가 없다는 점에 유의하십시오. *-stubs라는 이름만으로도 타이핑 정보의 출처임을 나타내기에 충분하기 때문입니다.

스텁 파일을 배포하려는 서드파티는 패키지와 함께 배포하는 것에 대해 해당 패키지의 유지 관리자에게 연락할 것을 권장합니다. 유지 관리자가 스텁 파일이나 인라인 타입 정보를 유지 관리하거나 패키징하기를 원하지 않는다면, 서드파티 스텁 전용 패키지를 만들 수 있습니다.

또한 스텁 전용 배포는 일반적인 의존성 데이터를 통해 런타임 배포의 버전을 명시함으로써 런타임 패키지의 어떤 버전을 지원하는지 표시해야 합니다(SHOULD). 예를 들어, 스텁 패키지 flyingcircus-stubs는 distutils 기반 도구의 install_requires나 다른 패키징 도구의 동등한 기능을 통해 자신이 지원하는 런타임 flyingcircus 배포의 버전을 표시할 수 있습니다. pip 9.0에서는 flyingcircus-stubs를 업데이트하면 flyingcircus도 업데이트된다는 점에 유의하십시오. pip 9.0에서는 --upgrade-strategy=only-if-needed 플래그를 사용할 수 있습니다. pip 10.0에서는 이것이 기본 동작입니다.

네임스페이스 패키지(PEP 420 참고)의 경우, 스텁 전용 패키지는 루트 네임스페이스 패키지에만 -stubs 접미사를 사용해야 합니다. 모든 스텁 전용 네임스페이스 패키지는 __init__.pyi 파일을 생략해야 합니다. 스텁 전용 패키지에는 py.typed 마커 파일이 필요하지 않지만, 인라인 타입이 있는 패키지와 마찬가지로 사용하는 경우에는 충돌을 피하고 명확성을 높이기 위해 네임스페이스의 하위 모듈에 두어야 합니다.

예를 들어, pentagon과 hexagon이 네임스페이스 패키지 shapes.polygons 안에 설치되는 별도의 배포라면, 대응하는 타입 전용 배포는 다음과 같이 배치된 패키지를 만들어야 합니다:

shapes-stubs
└── polygons
    └── pentagon
        └── __init__.pyi

shapes-stubs
└── polygons
    └── hexagon
        └── __init__.pyi

타입 검사기 모듈 해석 순서

다음은 이 PEP를 지원하는 타입 검사기가 타입 정보를 담은 모듈을 해석해야 하는(SHOULD) 순서입니다.

  1. 경로의 맨 앞에 수동으로 넣은 스텁 또는 Python 소스입니다. 타입 검사기는 사용자가 어떤 스텁을 사용할지 완전히 제어하고 패키지의 망가진 스텁/인라인 타입을 패치할 수 있도록 이 기능을 제공해야 합니다(SHOULD). mypy에서는 $MYPYPATH 환경 변수를 이 용도로 사용할 수 있습니다.
  2. 사용자 코드 - 타입 검사기가 검사하는 대상 파일입니다.
  3. 스텁 패키지 - 이 패키지는 설치된 모든 인라인 패키지보다 우선해야 합니다(SHOULD). foopkg 패키지의 스텁 패키지는 foopkg-stubs에서 찾을 수 있습니다.
  4. py.typed 마커 파일이 있는 패키지 - 설치된 패키지를 재정의하는 것이 없고 그리고 패키지가 타입 검사에 참여하기로 했다면, 패키지에 함께 들어 있는 타입을 사용해야 합니다(SHOULD)(해당 타입이 .pyi 타입 스텁 파일에 있든 .py 파일에 인라인으로 있든 관계없습니다).
  5. Typeshed(사용하는 경우) - 표준 라이브러리 타입과 여러 서드파티 라이브러리의 타입을 제공합니다.

타입 검사기가 3단계에서 원하는 모듈이 없는 스텁 전용 네임스페이스 패키지를 발견하면 4/5단계로 넘어가야 합니다. 타입 검사기는 __init__.pyi가 없다는 점을 기준으로 네임스페이스 패키지를 식별해야 합니다. 이렇게 하면 서로 다른 하위 패키지가 인라인 방식과 스텁 전용 방식 중 하나를 각자 독립적으로 선택할 수 있습니다.

자신이 실행되는 Python 버전과 다른 버전을 검사하는 타입 검사기는 검사 대상 Python 버전의 site-packages/dist-packages에서 타입 정보를 찾아야 합니다(MUST). 이 경로는 예를 들어 pythonX.Y -c 'import site; print(site.getsitepackages())'로 조회할 수 있습니다. 또한 Python 바이너리가 경로에 없는 경우를 대비해, 타입 검사기가 사용자에게 특정 Python 바이너리를 지정할 수 있게 하는 것을 권장합니다.

부분 스텁 패키지

많은 스텁 패키지는 라이브러리 타입 인터페이스의 일부만 완성된 상태일 것이며, 특히 초기에는 더욱 그렇습니다. 타입 검사와 코드 편집기를 위해 패키지는 “부분(partial)” 패키지가 될 수 있습니다. 이는 스텁 패키지에 없는 모듈을 위 모듈 해석 순서의 4단계와 5단계, 즉 인라인 패키지와 typeshed에서 찾아야 함(SHOULD)을 의미합니다.

타입 검사기는 스텁 패키지와 런타임 패키지 또는 typeshed 디렉터리를 병합해야 합니다. 이는 스텁 패키지를 대응하는 런타임 패키지 또는 typeshed 폴더와 같은 디렉터리에 복사한 뒤, 합쳐진 디렉터리 구조를 타입 검사하는 것과 기능적으로 같다고 볼 수 있습니다. 따라서 타입 검사기는 *.py 파일보다 *.pyi 파일을 먼저 검사하는 일반적인 해석 순서를 유지해야 합니다(MUST).

스텁 패키지 배포판이 부분 패키지라면 py.typed 파일에 partial\n을 포함해야 합니다(MUST). 네임스페이스 패키지 안에서 배포되는 스텁 패키지(PEP 420 참고)의 경우, py.typed 파일은 네임스페이스의 하위 모듈에 있어야 합니다.

네임스페이스 패키지는 여러 배포판이 내용을 채울 수 있으므로, 타입 검사기는 스텁 패키지 안의 네임스페이스 패키지를 불완전한 것으로 취급해야 합니다. 스텁 패키지 배포판에서 네임스페이스 패키지 안에 있는 일반 패키지는 partial\n이 들어 있는 py.typed가 포함되지 않는 한 완전한 것으로 간주합니다.

구현

제안된 타이핑 지원 표시 방식은 하위 호환성을 완전히 유지하며, 패키지 도구를 수정할 필요가 없습니다. 인라인 타입이 있는 샘플 패키지 [typed_package]와 [stub_package]를 사용할 수 있습니다. 설치된 패키지의 메타데이터를 읽고 각 패키지가 타입이 없는지, 인라인 타입이 있는지, 스텁 패키지인지를 알려 주는 샘플 패키지 검사기 [pkg_checker]도 있습니다.

mypy 타입 검사기에는 PEP 561 검색 구현이 있으며, 자세한 내용은 mypy 문서 [4]에서 읽을 수 있습니다.

[numpy-stubs]는 numpy 배포판을 위한 실제 스텁 전용 패키지의 예입니다.

감사의 글

이 PEP는 Ivan Levkivskyi, Jelle Zijlstra, Alyssa Coghlan, Daniel F Moisset, Andrey Vlasovskikh, Nathaniel Smith, Guido van Rossum의 아이디어와 피드백, 지원이 없었다면 불가능했을 것입니다.

버전 이력

  • 2023-01-13
    • 모듈 해석 순서의 4번째 단계가 인라인 패키지뿐만 아니라 py.typed 마커 파일이 있는 모든 패키지에 적용된다는 점을 명확히 했습니다.
  • 2021-09-20
    • 스텁 전용 네임스페이스 패키지에 대한 기대 사항과 타입 검사기 동작을 명확히 했습니다.
    • 네임스페이스 패키지 안의 단일 파일 모듈 처리 방식을 명확히 했습니다.
  • 2018-07-09
    • 스텁 전용 패키지 예시 링크를 추가했습니다.
  • 2018-06-19
    • 부분 스텁 패키지는 런타임 패키지뿐만 아니라 typeshed도 참조할 수 있습니다.
  • 2018-05-15
    • 부분 스텁 패키지 명세를 추가했습니다.
  • 2018-04-09
    • mypy 구현에 대한 참조를 추가했습니다.
    • 스텁 패키지 우선순위를 명확히 했습니다.
  • 2018-02-02
    • 스텁 전용 패키지 접미사를 _stubs가 아닌 -stubs로 변경했습니다.
    • 스텁 전용 패키지에는 py.typed가 필요하지 않다는 점을 명시했습니다.
    • pip와 스텁 패키지 업그레이드에 관한 참고 사항을 추가했습니다.
  • 2017-11-12
    • 기존 도구만 사용하도록 다시 작성했습니다.
    • 메타데이터에 타입 정보의 종류를 표시할 필요가 없어졌습니다.
    • 마커 파일 이름을 .typeinfo에서 py.typed로 변경했습니다.
  • 2017-11-10
    • 배포 메타데이터 대신 패키지 메타데이터를 사용하도록 명세를 다시 작성했습니다.
    • 스텁 전용 패키지 항목을 제거하고 서드파티 패키지 명세에 병합했습니다.
    • 타입 검사기가 런타임 버전 검사를 고려하도록 하는 제안을 제거했습니다.
    • PEP 변경 사항을 반영하도록 구현을 업데이트했습니다.
  • 2017-10-26
    • 구현 참조를 추가했습니다.
    • 감사의 글과 버전 이력을 추가했습니다.
  • 2017-10-06
    • distutils 전용 명령 대신 .distinfo/METADATA 메타데이터를 사용하도록 다시 작성했습니다.
    • 서드파티 스텁 패키지의 버전 관리 방식을 명확히 했습니다.
  • 2017-09-11
    • 현재 사용되는 해결책과 typeshed에 관한 정보를 추가했습니다.
    • 근거를 명확히 했습니다.

참고 문헌