PEP 426 – Python 소프트웨어 패키지를 위한 메타데이터 2.0
- Author:
- Alyssa Coghlan <ncoghlan at gmail.com>, Daniel Holth <dholth at gmail.com>, Donald Stufft <donald at stufft.io>
- BDFL-Delegate:
- Donald Stufft <donald at stufft.io>
- Discussions-To:
- Distutils-SIG list
- Status:
- Withdrawn
- Type:
- Informational
- Topic:
- Packaging
- Requires:
- 440, 508, 518
- Created:
- 30-Aug-2012
- Post-History:
- 14-Nov-2012, 05-Feb-2013, 07-Feb-2013, 09-Feb-2013, 27-May-2013, 20-Jun-2013, 23-Jun-2013, 14-Jul-2013, 21-Dec-2013
- Replaces:
- 345
- Superseded-By:
- 566
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Python 배포물과 관련된 메타데이터를 게시하고 교환하는 메커니즘을 설명합니다. 여기에는 필드 이름의 세부 사항과 각 필드의 의미 및 사용법이 포함됩니다.
이 문서는 한 번도 릴리스되지 않은 메타데이터 형식 버전 2.0을 명세합니다.
버전 1.0은 PEP 241에 명세되어 있습니다. 버전 1.1은 PEP 314에 명세되어 있습니다. 버전 1.2는 PEP 345에 명세되어 있습니다.
메타데이터 형식 버전 2.0은 사용자 정의 키-값 파일 형식을 직접 정의하는 방식에서 벗어나, 다른 맥락(API 및 아카이브 형식 정의 등)에서 메타데이터 표현을 정의하는 데 사용할 수 있는 JSON 호환 인메모리 표현을 정의하는 방식으로 전환할 것을 제안했습니다.
이 버전은 또한 공식적인 확장 메커니즘을 정의하여, 코어 메타데이터 형식을 갱신하지 않고도 특정 목적을 위해 새 필드를 추가할 수 있게 합니다.
PEP 이력에 관한 참고 사항
이 PEP는 distutils-sig가 여러 다른 변경 사항을 처리하는 동안 처음에 2013년 12월부터 2017년 3월까지 오랜 기간 보류되었습니다. 이러한 변경 사항은 다음과 같습니다:
- PEP 425에서 바이너리 호환성 태깅 형식 정의
- PEP 427에서 바이너리 아카이브 형식(
wheel) 정의 - PEP 440에서 버전 관리 및 버전 비교를 명시적으로 정의
- PEP 503에서 PyPI “simple” API를 명시적으로 정의
- PEP 508에서 의존성 지정자와 extras 시스템을 명시적으로 정의
- PEP 518에서 정적 빌드 시스템 의존성(
pyproject.toml) 선언 - PyPI 호스팅을 Rackspace로 이전하고 Fastly CDN 뒤에 배치
- PEP 453에서 CPython에
pip을 기본으로 포함하여 배포하고, PEP 477에서 그 추가 사항을 Python 2.7에 백포트 - packaging.python.org를 Python 패키징 생태계 문서의 공통 접근 지점으로 확립
- packaging.python.org의 specifications 섹션을 패키징 관련 PEP를 추적하는 중심 위치로 사용하도록 전환
이러한 변경 사항을 추진하는 데 들인 시간 덕분에, 어떤 메타데이터 형식 변경이 진정으로 바람직하고 어떤 변경이 단지 “변경을 위한 변경”에 불과하여 개정된 명세에서 생략할 수 있는지에 대해 추가적인 관점을 얻을 수 있었습니다.
또한 이를 통해 소프트웨어를 게시하고 배포하는 핵심 활동에 필수적이지 않은 여러 기능을 PEP 459로 옮길 수 있었습니다. 이 PEP는 릴리스에 관한 선택적 추가 정보를 제공하는 여러 표준 메타데이터 확장을 다루는 별도의 제안입니다.
2017년 9월에는 특별히 시급한 문제를 해결하는 데 실제로 도움이 되지 않는다는 이유로 다시 보류되었습니다:
- JSON 표현은 기존 메타데이터 1.2 필드의 변환을 정의하는 방식으로 다루는 것이 더 낫습니다
- 지난 몇 년간 정의된 추가 필드의 명확화와 이와 관련된 명세 관리 절차의 변경은 minor spec version update에서 다루는 것이 더 낫습니다
결국 이 PEP는 2018년 2월에 (더 점진적인 전략을 추구하는) PEP 566으로 대체되어 철회되었습니다.
목적
이 PEP의 목적은 Python 생태계에서 소프트웨어 게시 도구와 소프트웨어 통합 도구가 서로 소통하는 데 쓰는 공통 메타데이터 교환 형식을 정의하는 것입니다. 핵심 목표 중 하나는 분석을 수행하는 쪽이 임의의 Python 코드를 실행하지 않아도 이 생태계에서 완전한 의존성 분석을 할 수 있도록 지원하는 것입니다. 또 다른 목표는 Python 패키지 색인을 사용하는 기존 사용자(게시자와 통합자 모두) 거의 전부의 현재 관행을 계속 지원하면서, 기본적으로 좋은 소프트웨어 배포 관행을 장려하는 것입니다. 마지막으로, 현재 사용 중인 메타데이터 형식에서 최종 사용자에게 투명한 업그레이드 경로를 지원하는 것을 목표로 합니다.
이 설계는 distutils 기반 소프트웨어 배포에 관한 Python 커뮤니티의 약 20년 경험을 바탕으로 하며, Python의 setuptools, pip 및 기타 프로젝트, Ruby의 gems, Perl의 CPAN, Node.js의 npm, PHP의 composer, 그리고 RPM과 APT 같은 Linux 패키징 시스템 등 다른 배포 시스템의 아이디어와 개념도 받아들였습니다.
이 형식의 세부 사항은 Python 생태계를 겨냥하고 있지만, 일부 아이디어는 앞으로 다른 의존성 관리 생태계가 발전하는 데에도 유용할 수 있습니다.
Python 소프트웨어의 개발, 배포, 디플로이
이 PEP의 메타데이터 설계는 소프트웨어 개발 및 배포 과정에 대한 특정한 개념 모델에 기반합니다. 이 모델은 다음 단계로 구성됩니다:
- 소프트웨어 개발: 이 단계에서는 특정 애플리케이션의 소스 체크아웃으로 작업하면서 기능을 추가하고 버그를 수정합니다. 이 단계의 개발자는 소프트웨어를 빌드하고, 소프트웨어의 자동화된 테스트 스위트를 실행하고, 프로젝트 전용 유틸리티 스크립트를 실행하고, 소프트웨어를 게시할 수 있어야 할 것으로 예상됩니다.
- 소프트웨어 게시: 이 단계에서는 개발된 소프트웨어를 받아 소프트웨어 통합자가 사용할 수 있도록 제공합니다. 여기에는 이 PEP에서 정의하는 기술(記述) 메타데이터를 만드는 일과 소프트웨어를 사용할 수 있게 하는 일(보통 색인 서버에 업로드하는 방식)이 포함됩니다.
- 소프트웨어 통합: 이 단계에서는 게시된 소프트웨어 구성 요소를 받아 일관성 있는 하나의 통합 시스템으로 결합합니다. 이 작업은 Python 전용 크로스 플랫폼 도구로 직접 할 수도 있고, 개발 언어와 무관한 플랫폼별 패키징 시스템으로 변환하여 처리할 수도 있습니다.
- 소프트웨어 배포: 이 단계에서는 통합된 소프트웨어 구성 요소를 가져와 소프트웨어가 실제로 실행될 대상 시스템에 배포합니다.
게시 단계와 통합 단계를 합쳐 배포 단계라고 부르며, 이 단계에서 배포되는 개별 소프트웨어 구성 요소를 공식적으로는 “배포 패키지”라고 하지만 흔히는 그냥 “패키지”라고 부릅니다(Python 패키지 중 “하위 모듈을 가진 모듈”이라는 뜻의 패키지와는 문맥으로 구별합니다).
이 단계들의 정확한 세부 사항은 사용 사례에 따라 크게 달라집니다. 공개 PaaS(Platform-as-a-Service, 서비스형 플랫폼) 제공자에 웹 애플리케이션을 배포하는 것, 웹 프레임워크나 과학 라이브러리의 새 릴리스를 게시하는 것, 통합된 Linux 배포판을 만드는 것, 보안 격리 영역(secure enclave)에서 실행되는 맞춤형 애플리케이션을 업그레이드하는 것은 모두 이 메타데이터 설계가 처리할 수 있어야 하는 상황입니다.
따라서 이 PEP에서 설명하는 메타데이터의 복잡성은 다양한 시나리오에서 소프트웨어 개발, 배포, 디플로이에 따르는 실제 복잡성에서 직접 비롯됩니다.
보조 정의
이 문서에 나오는 핵심어 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”은 RFC 2119에 설명된 대로 해석해야 합니다.
“프로젝트”는 통합에 쓸 수 있도록 제공되는 소프트웨어 구성 요소입니다. 프로젝트에는 Python 라이브러리, 프레임워크, 스크립트, 플러그인, 애플리케이션, 데이터나 기타 리소스의 모음, 그리고 이들의 다양한 조합이 포함됩니다. 공개 Python 프로젝트는 보통 Python Package Index에 등록됩니다.
“릴리스”는 고유하게 식별되는 프로젝트의 스냅숏입니다.
“배포 패키지”는 릴리스를 게시하고 배포하는 데 사용하는 패키징된 파일입니다.
문맥에 따라 “패키지”는 배포판을 가리킬 수도 있고, __path__ 속성이 있어서 임포트할 수 있는 하위 모듈도 가질 수 있는 임포트 가능한 Python 모듈을 가리킬 수도 있습니다.
“소스 아카이브”와 “VCS 체크아웃”은 둘 다 sdist나 바이너리 아카이브를 만들기 전의 릴리스 원본 소스 코드를 가리킵니다.
“sdist”는 배포 메타데이터와 함께, 배포판의 바이너리 아카이브를 만드는 데 꼭 필요한 소스 파일을 제공하는 게시 형식입니다. sdist에서 바이너리 아카이브를 만들려면 시스템에 적절한 빌드 도구가 있어야 합니다.
“바이너리 아카이브”는 미리 빌드된 파일을 대상 시스템의 올바른 위치로 옮기기만 하면 됩니다. Python은 동적으로 바인딩되는 크로스 플랫폼 언어이므로, 이른바 “바이너리” 아카이브 중 상당수는 순수 Python 소스 코드만 담고 있을 것입니다.
“기여자”는 소프트웨어 구성 요소를 개발하기 위해 함께 작업하는 개인과 조직입니다.
“게시자”는 소프트웨어 구성 요소를 통합에 사용할 수 있도록 제공하는 개인과 조직입니다(일반적으로 배포본을 색인 서버에 업로드하는 방식으로 제공합니다)
“통합자”는 게시된 배포본을 애플리케이션이나 더 큰 시스템의 구성 요소로 편입하는 개인과 조직입니다.
“빌드 도구”는 개발 시스템에서 실행되도록 만들어진 자동화 도구로, 소스 배포 아카이브와 바이너리 배포 아카이브를 생성합니다. 빌드 도구는 미리 빌드된 바이너리 아카이브가 아니라 sdist로 배포된 소프트웨어를 빌드하기 위해 통합 도구에 의해 호출될 수도 있습니다.
“색인 서버”는 버전 및 의존성 메타데이터를 게시하고 허용되는 메타데이터에 제약을 두는 능동적인 배포본 레지스트리입니다.
“공개 색인 서버”는 신뢰할 수 없는 서드파티의 배포 업로드를 허용하는 색인 서버입니다. Python Package Index는 공개 색인 서버입니다.
“게시 도구”는 개발 시스템에서 실행되도록 만들어진 자동화 도구로, 소스 배포 아카이브와 바이너리 배포 아카이브를 색인 서버에 업로드합니다.
“통합 도구”는 색인 서버나 기타 지정된 출처에서 게시한 메타데이터와 배포 아카이브를 받아, 이를 설치하거나 플랫폼별 패키징 형식으로 변환하는 등 어떤 방식으로든 활용하는 자동화 도구입니다.
“설치 도구”는 특별히 배포 대상에서 실행되도록 만들어진 통합 도구로, 색인 서버나 기타 지정된 위치에서 소스 배포 아카이브와 바이너리 배포 아카이브를 받아 대상 시스템에 배포합니다.
“자동화 도구”는 빌드 도구, 색인 서버, 게시 도구, 통합 도구, 그리고 배포본의 버전 및 의존성 메타데이터를 생성하거나 소비하는 기타 모든 소프트웨어를 아우르는 총칭입니다.
“레거시 메타데이터”는 이 메타데이터 명세의 이전 버전과, setuptools 프로젝트에서 정의한 보조 메타데이터 파일 형식을 가리킵니다.
“배포판(Distro)”은 Linux 배포판을 가리키는 선호 용어로 사용되며, 이는 Python에서 특정하게 쓰이는 “배포 패키지”라는 용어와의 혼동을 피하기 위함입니다.
“정규화된 이름”은 점으로 구분된 Python 식별자입니다. 임포트된 모듈과 패키지의 경우 정규화된 이름은 __name__ 속성으로 얻을 수 있으며, 함수와 클래스의 경우 __qualname__ 속성으로 얻을 수 있습니다.
“완전한 정규화된 이름”은 Python 모듈 네임스페이스에서 객체의 위치를 고유하게 지정합니다. 임포트된 모듈과 패키지의 경우 이는 정규화된 이름과 같습니다. 그 밖의 Python 객체의 경우, 완전한 정규화된 이름은 객체를 포함하는 모듈이나 패키지의 정규화된 이름, 콜론(:), 그리고 포함하는 모듈이나 패키지를 기준으로 한 객체의 정규화된 이름으로 구성됩니다.
“접두 이름”은 정규화된 이름으로 시작하지만 반드시 정규화된 이름인 것은 아닙니다. 유효한 식별자가 아닌, 점으로 구분된 추가 구간을 포함할 수 있습니다.
배포본의 통합과 배포
배포본 메타데이터의 주된 목적은 더 큰 애플리케이션과 시스템의 일부로서 배포본을 통합하고 배포하는 작업을 지원하는 것입니다.
통합과 배포는 다시 더 세부적인 단계로 나눌 수 있습니다.
- 빌드: 빌드 단계는 VCS 체크아웃, 소스 아카이브 또는 sdist를 바이너리 아카이브로 변환하는 과정입니다. 배포본을 빌드하고 바이너리 아카이브(대상 시스템에 설치되는 모든 문서 포함)를 생성하려면 의존성을 사용할 수 있어야 합니다.
- 설치: 설치 단계는 배포본과 그 모든 런타임 의존성을 대상 시스템에 들여놓는 과정입니다. 이 단계에서 배포본은 이미 시스템에 존재할 수도 있고(업그레이드나 재설치의 경우), 완전히 새로 설치되는 것일 수도 있습니다.
- 런타임: 배포본이 대상 시스템에 설치된 후 이를 일반적으로 사용하는 단계입니다.
이 세 단계는 모두 대상 시스템에서 직접 이루어질 수 있습니다. 또는 배포판 게시자가 제공하는 바이너리 아카이브를 사용하거나, 배포 전에 별도의 시스템에서 바이너리 아카이브를 만들어서 빌드 단계를 분리할 수도 있습니다. 후자 방식의 장점은 배포 대상에 설치해야 하는 의존성을 최소화한다는 점입니다(빌드 의존성은 빌드 시스템에서만 필요하기 때문입니다).
배포 패키지에 대해 게시된 메타데이터는 통합자가 빌드 및 통합 도구의 도움을 받아 다음을 할 수 있도록 해야 합니다:
- 배포판을 만드는 데 사용된 원본 소스 코드 얻기
- 배포판을 사용하는 데 필요한 의존성(있는 경우)을 식별하고 가져오기
- 소스에서 배포판을 빌드하는 데 필요한 의존성(있는 경우)을 식별하고 가져오기
- 배포판의 테스트 스위트를 실행하는 데 필요한 의존성(있는 경우)을 식별하고 가져오기
배포판의 개발 및 게시
배포판 메타데이터의 두 번째 목적은 개발 단계에서 소프트웨어 기여자와 게시자 사이의 효과적인 협업을 지원하는 것입니다.
배포판에 대해 게시된 메타데이터는 기여자와 게시자가 빌드 및 게시 도구의 도움을 받아 다음을 할 수 있도록 해야 합니다:
- 배포판을 효과적으로 통합하고 배포하는 데 필요한 모든 활동을 똑같이 수행하기
- 배포판을 개발하고 게시하는 데 필요한 추가 의존성을 식별하고 가져오기
- 배포판을 사용하는 데 필요한 의존성(있는 경우)을 지정하기
- 소스에서 배포판을 빌드하는 데 필요한 의존성(있는 경우)을 지정하기
- 배포판의 테스트 스위트를 실행하는 데 필요한 의존성(있는 경우)을 지정하기
- 배포판을 개발하고 게시하는 데 필요한 추가 의존성(있는 경우)을 지정하기
메타데이터 형식
이 PEP에서 정의하는 형식은 Python 배포판 메타데이터를 문자열 키 딕셔너리로 나타낸 메모리 내 표현입니다. 개별 항목에 허용되는 값은 문자열, 문자열의 리스트, 그리고 추가로 중첩된 문자열 키 딕셔너리입니다.
달리 명시된 경우를 제외하고, 배포판 메타데이터의 딕셔너리 키는 속성 기반 메타데이터 접근 API를 지원하기 위해 유효한 Python 식별자여야 합니다.
개별 필드 설명에서는 JSON 매핑의 일부로 직렬화될 때의 키 이름과 값의 예를 보여 줍니다.
달리 명시되지 않는 한, 코어 메타데이터로 식별된 필드는 필수입니다. 자동화 도구는 코어 메타데이터가 누락된 배포를 유효한 Python 배포로 받아들여서는 안 됩니다(MUST NOT).
그 밖의 모든 필드는 선택 사항입니다. 자동화 도구는 배포판이 이러한 필드를 제공하지 않더라도 올바르게 동작해야 합니다. 단, 생략된 필드를 특별히 필요로 하는 작업은 예외입니다.
자동화 도구는 누락된 필드에 더미 데이터를 삽입해서는 안 됩니다. 필수 필드에 유효한 값이 제공되지 않으면, 해당 메타데이터와 관련 배포판은 유효하지 않은 것으로 거부되어야 합니다. 선택 필드에 유효한 값이 제공되지 않으면, 해당 필드는 완전히 생략되어야 합니다. 자동화 도구는 다른 정보 출처(예: 버전 관리 시스템)에서 유효한 값을 자동으로 도출할 수 있습니다.
자동화 도구, 특히 공개 색인 서버는 이 PEP에 열거된 것 외에 메타데이터에 추가 길이 제한을 부과할 수 있습니다. 이러한 제한은 가용 자원과 합리적인 메타데이터 용량 요구 사항에 대한 서비스 제공자의 판단에 따라, 서비스의 무결성을 보호하는 데 필요한 경우에 부과해야 합니다.
메타데이터 파일
일부 사용 사례에서는 이 PEP에서 정의하는 정보를 pysdist.json 파일로 직렬화합니다. 이 파일에는 UTF-8로 인코딩된 JSON 메타데이터가 담겨 있습니다.
각 메타데이터 파일은 직렬화된 매핑 하나로 구성되며, 이 매핑에는 이 PEP에서 설명하는 필드가 들어 있습니다. 메타데이터를 직렬화할 때 자동화 도구는 변경 사항을 쉽게 검토할 수 있도록 모든 키와 리스트 요소를 사전순으로 정렬해야 합니다(SHOULD).
이 메타데이터 파일의 표준 위치는 다음 세 곳이 될 것으로 예상됩니다.
sdist소스 배포판 아카이브 안의{distribution}-{version}.dist-info/pysdist.json파일로wheel바이너리 배포 아카이브 안의{distribution}-{version}.dist-info/pysdist.json파일- 로컬 Python 설치 데이터베이스 안의
{distribution}-{version}.dist-info/pysdist.json파일로
이 파일은 세 위치 모두에서 동일할 것으로 예상됩니다. 이 파일은 소스 트리에서 소스 아카이브나 바이너리 아카이브를 만들 때 생성됩니다. 그 후 설치할 때나 소스 아카이브에서 바이너리 아카이브를 빌드할 때에도 바뀌지 않고 그대로 유지됩니다.
Note
이 위치들은 sdist 2.0의 정의와 개정된 설치 데이터베이스 표준에 따라 달라지므로 아직 확정되지 않았습니다. 또한 이 PEP가 승인된 후에는 wheel 1.1 형식 업데이트가 있을 예정이며, 이 업데이트는 2.0 이상의 메타데이터를 제공하도록 의무화합니다.
이 메타데이터 파일이 들어 있는 위치의 버전이 너무 낮아서 파일이 유효하다고 볼 수 없더라도 이 파일을 처리할 수 있습니다(MAY). 이 점에 유의하십시오. 구체적으로 말하면, 버전이 없는 sdist 아카이브와 버전이 없는 설치 데이터베이스 디렉터리, wheel 명세 버전 1.0에서도 pysdist.json 파일을 제공할 수 있습니다.
Note
이 명세가 공식적으로 Active로 표시되기 전까지는 초안 형식을 따르는 도구가 metadata.json이나 pep426-20131213.json 같은 다른 파일 이름을 사용하기를 권장합니다. 그래야 나중에 표준화될 파일과 충돌하지 않습니다.
Python 배포에 관여하는 다른 도구도 이 형식을 사용할 수 있습니다(MAY).
이 메타데이터 파일은 데이터 입력 형식으로 직접 쓰이지 않습니다. 빌드 도구가 다른 입력 형식(setup.py나 pyproject.toml 등)을 바탕으로 생성한다는 점에 유의하십시오. 게시 과정에서 메타데이터를 생성하면 버전별 필드(소스 URL과 버전 필드 자체 포함)를 처리하는 데에도 도움이 됩니다.
오래된 설치 도구와의 하위 호환성을 위해 메타데이터 2.0 파일을 레거시 메타데이터와 함께 배포할 수 있습니다(MAY).
색인 서버는 레거시 메타데이터만 있는 배포 패키지의 업로드를 허용할 수 있습니다(MAY). 설치 도구도 이러한 배포 패키지의 설치를 허용할 수 있습니다(MAY).
자동화 도구는 레거시 메타데이터를 이 PEP에서 설명하는 형식으로 자동 변환하려고 시도할 수 있습니다(MAY). 이 변환을 효과적으로 수행하는 방법은 부록 A에서 안내합니다.
메타데이터 검증
배포 메타데이터를 기술하는 jsonschema 명세가 공개되어 있습니다.
이 스키마는 현재 일부 복잡한 문자열 필드의 검증을 처리하지 않습니다(NOT). 이러한 필드는 불투명한 문자열로 취급합니다.
달리 명시한 경우를 제외하고, 메타데이터의 모든 URL 필드는 RFC 3986을 준수해야 합니다(MUST).
Note
현재 버전의 스키마 파일은 이 PEP의 이전 초안을 기준으로 합니다. 메타데이터를 필수 의존성 해석 메타데이터와 여러 표준 확장으로 나눈 변경은 아직 반영되지 않았습니다. 현재 초안과 이전 초안 사이의 여러 다른 차이점도 아직 반영되지 않았습니다.
코어 메타데이터
이 절에서는 모든 Python 배포에 필수인 코어 메타데이터 필드를 명세합니다.
게시 도구는 배포 패키지를 게시할 때 최소한 이 필드들이 있는지 확인해야 합니다(MUST).
색인 서버는 배포 패키지가 업로드될 때 메타데이터에 최소한 이 필드들이 있는지 확인해야 합니다(MUST).
이 필드 중 하나라도 빠진 배포 패키지는 설치 도구가 기본적으로 설치를 거부해야 합니다(MUST). 다만 사용자가 설치를 강제로 진행하도록 허용할 수 있습니다(MAY).
메타데이터 버전
파일 형식의 버전입니다. 허용되는 값은 "2.0"뿐입니다.
메타데이터를 사용하는 자동화 도구는 metadata_version이 지원하는 가장 높은 버전보다 높으면 경고해야 하며(SHOULD), metadata_version의 메이저 버전이 지원하는 가장 높은 버전의 메이저 버전보다 높으면 실패해야 합니다(MUST). (PEP 440에서 설명하는 것처럼 메이저 버전은 첫 번째 점 앞의 값입니다.)
더 폭넓은 호환성을 위해 빌드 도구는 필요한 필드를 모두 포함하는 가장 낮은 메타데이터 버전으로 배포 메타데이터를 생성할 수 있습니다(MAY).
예시:
"metadata_version": "2.0"
제너레이터
파일을 생성한 프로그램이 있다면 그 이름(및 선택적으로 버전)입니다. 수동으로 작성한 파일에서는 이 필드를 생략합니다.
예시:
"generator": "flit"
"generator": "setuptools (34.3.1)"
이름
PEP 508에 정의된 배포의 이름입니다.
배포 이름은 URL, 파일 이름, 명령줄 매개변수의 일부로 사용되며 다른 패키징 시스템과도 상호 운용되어야 하므로, 허용되는 문자는 다음으로 제한됩니다.
- ASCII 문자 (
[a-zA-Z]) - ASCII 숫자 (
[0-9]) - 밑줄 (
_) - 하이픈 (
-) - 마침표 (
.)
배포 이름은 ASCII 문자나 숫자로 시작하고 끝나야 합니다(MUST).
자동화 도구는 규칙을 따르지 않는 이름을 거부해야 합니다(MUST). 이 제약 조건을 강제하는 정규 표현식(re.IGNORECASE로 실행할 때)은 다음과 같습니다.:
^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$
배포 이름 비교는 모두 대소문자를 구분하지 않아야 하며(MUST), 하이픈과 밑줄을 동등하게 취급해야 합니다(MUST).
색인 서버는 (유니코드 컨소시엄이 TR39: Unicode Security Mechanisms에서 정의한) “혼동 가능한” 문자를 동등하게 취급할 수 있습니다(MAY).
신뢰할 수 없는 출처에서 임의의 배포 이름 등록을 허용하는 색인 서버는 새 배포를 등록할 때 혼동 가능한 문자를 동등하게 취급해야 하며(SHOULD), 따라서 그러한 배포를 중복으로 보고 거부해야 합니다.
통합 도구는 혼동 가능한 다른 철자를 요청된 배포 이름과 일치하는 것으로 조용히 받아들여서는 안 됩니다(MUST NOT).
이 글을 쓰는 시점에 유니코드 컨소시엄이 혼동 가능한 문자로 지정한 ASCII 부분 집합의 문자는 다음과 같습니다.
1(DIGIT ONE),l(LATIN SMALL LETTER L),I(LATIN CAPITAL LETTER I)0(DIGIT ZERO),O(LATIN CAPITAL LETTER O)
예시:
"name": "ComfyChair"
버전
PEP 440에 정의된 배포의 공개 또는 로컬 버전 식별자입니다. 버전 식별자는 자동화된 도구가 사용하도록 설계되었으며, 다양하고 유연한 버전 명세 메커니즘을 지원합니다(자세한 내용은 PEP 440을 참조하십시오).
버전 식별자는 PEP 440에 정의된 형식을 따라야 합니다(MUST).
버전 식별자는 각 프로젝트 안에서 반드시(MUST) 고유해야 합니다.
색인 서버는 PEP 440에 설명된 대로 로컬 버전 식별자 사용을 제한할 수 있습니다(MAY).
예시:
"version": "1.0a2"
요약
배포판이 하는 일을 짧게 요약한 내용입니다.
이 필드는 512자 미만이어야 하며(SHOULD), 반드시 2048자 미만이어야 합니다(MUST).
이 필드에는 줄 바꿈이 없어야 합니다(SHOULD NOT).
더 자세한 설명은 배포판의 sdist에 별도 파일로 포함해야 합니다(SHOULD). 자세한 내용은 PEP 459의 python-details 확장을 참조하십시오.
예시:
"summary": "A module that is more fiendish than soft cushions."
소스 코드 메타데이터
이 절에서는 이 배포판을 만드는 데 사용한 소스 코드의 식별 정보를 제공하는 필드를 정의합니다.
이 필드는 모두 선택 사항입니다. 배포판이 이 필드를 제공하지 않더라도 자동화 도구는 반드시(MUST) 올바르게 동작해야 합니다. 여기에는 이 필드 중 하나에 의존하는 작업이 요청되었을 때 깔끔하게 실패하는 것도 포함됩니다.
소스 레이블
소스 레이블은 정의된 의미가 최소한인 텍스트 문자열입니다. 소스 레이블은 통합자가 특정 배포판에 로컬 수정을 추가로 적용했더라도 원본 소스 코드를 모호함 없이 식별할 수 있게 하기 위한 것입니다.
소스 레이블을 파일 이름과 URL에 쉽게 넣을 수 있게 하고 16진수 해시 표현의 서식이 서로 달라지는 문제를 피하기 위해, 소스 레이블에는 반드시(MUST) 다음 문자만 사용해야 합니다:
- ASCII 소문자 (
[a-z]) - ASCII 숫자 (
[0-9]) - 밑줄 (
_) - 하이픈 (
-) - 마침표 (
.) - 더하기 기호 (
+)
소스 레이블은 반드시(MUST) ASCII 문자나 숫자로 시작하고 끝나야 합니다.
이 제약 조건을 강제하는 정규 표현식(re.IGNORECASE와 함께 실행할 때)은 다음과 같습니다:
^([A-Z0-9]|[A-Z0-9][A-Z0-9._-+]*[A-Z0-9])$
프로젝트의 소스 레이블은 그 프로젝트에 정의된 어떤 버전과도 일치해서는 안 됩니다(MUST NOT). 이 제한이 있으면 버전 식별자와 소스 레이블이 서로 헷갈릴 일이 없습니다.
예시:
"source_label": "1.0.0-alpha.1"
"source_label": "1.3.7+build.11.e0f985a"
"source_label": "v1.8.1.301.ga0df26f"
"source_label": "2013.02.17.dev123"
소스 URL
배포판의 이 버전에 해당하는 소스를 내려받을 수 있는 전체 URL이 담긴 문자열입니다.
소스 URL은 각 프로젝트 안에서 반드시 고유해야 합니다. 즉, URL은 "https://github.com/pypa/pip/archive/main.zip" 같은 형태가 될 수 없으며, 대신 "https://github.com/pypa/pip/archive/1.3.1.zip"이어야 합니다.
소스 URL은 반드시 소스 아카이브를 참조하거나, 적절한 VCS 체크아웃을 만들 수 있는 온라인 버전 관리 시스템의 태그 또는 특정 커밋을 참조해야 합니다. 이는 주로 원래의 소스 형태에서 배포판을 다시 만들고자 하는 통합자를 위한 것입니다.
모든 소스 URL 참조는 안전한 전송 메커니즘(예: https)을 지정해야 하며, 그와 함께 검증을 위해 예상 해시 값을 URL에 포함해야 합니다. 소스 URL에 해시 정보가 전혀 없거나, 도구가 이해하지 못하는 해시 정보가 있거나, 도구가 신뢰하기에 너무 약하다고 판단하는 해시 알고리즘이 선택된 경우, 자동화 도구는 최소한 경고를 내보내야 하며 해당 URL에 의존하기를 거부할 수 있습니다. 그러한 소스 URL이 안전하지 않은 전송 방식까지 사용한다면, 자동화 도구는 해당 URL에 의존해서는 안 됩니다.
소스 아카이브 참조의 경우, URL 프래그먼트의 일부로 <hash-algorithm>=<expected-hash> 항목을 포함하여 예상 해시 값을 지정할 수 있습니다.
2017년 기준으로 소스 URL에는 'sha256' 해시를 사용할 것을 권장합니다. 이 해시는 악의적인 충돌 생성에 취약하다고 아직 알려지지 않았으며, 동시에 클라이언트 시스템에서 널리 사용할 수 있기 때문입니다.
버전 관리 참조의 경우, 버전 관리 시스템과 안전한 전송 방식을 모두 식별하기 위해 VCS+protocol 스킴을 사용해야 하며, 해시 기반 커밋 식별자를 사용하는 버전 관리 시스템을 사용해야 합니다. 해시 기반 커밋 식별자를 제공하지 않는 버전 관리 시스템에 대해서는 자동화 도구가 해시 누락 경고를 생략할 수 있습니다.
URL에 커밋이나 태그 참조를 직접 포함하는 것을 지원하지 않는 버전 관리 시스템을 처리하기 위해, @<commit-hash> 또는 @<tag>#<commit-hash> 표기법을 사용하여 해당 정보를 URL 끝에 덧붙일 수 있습니다.
Note
이는 pip가 지원하는 기존 VCS 참조 표기법과 완전히 같지는 않습니다. 첫째, 배포판 이름은 URL의 일부로 포함되는 것이 아니라 별도의 필드입니다. 둘째, 위조를 더 어렵게 하기 위해 모든 링크에 해시를 포함해야 한다는 위의 요구 사항을 충족하도록, 태그를 기준으로 가져오는 경우에도 커밋 해시를 포함합니다(특정 태그를 가진 악의적인 저장소를 만들기는 쉽지만, 특정 해시를 가진 저장소를 만들기는 그만큼 쉽지 않습니다).
예시:
"source_url": "https://github.com/pypa/pip/archive/1.3.1.zip#sha256=2dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db8
"source_url": "git+https://github.com/pypa/pip.git@1.3.1#7921be1537eac1e97bc40179a57f0349c2aee67d"
"source_url": "git+https://github.com/pypa/pip.git@7921be1537eac1e97bc40179a57f0349c2aee67d"
의미론적 의존성
의존성 메타데이터를 사용하면 공개된 프로젝트가 다른 공개된 프로젝트의 특정 릴리스 사본을 함께 묶을 필요 없이 그 프로젝트가 제공하는 기능을 활용할 수 있습니다.
의미론적 의존성을 사용하면 게시자는 어떤 다른 프로젝트가 필요한지뿐만 아니라 그 프로젝트가 왜 필요한지도 나타낼 수 있습니다. 이 추가 정보를 통해 통합자는 특정 작업에 필요한 의존성만 설치할 수 있으므로, 제약이 있는 환경에서 설치 공간을 최소화하기가 더 쉬워집니다(그러한 제약이 생긴 이유와는 관계없이 그렇습니다).
기본적으로 의존성 선언은 “런타임 의존성”, 즉 공개된 릴리스를 실제로 사용하는 데 필요한 다른 릴리스에 대한 것으로 간주됩니다.
릴리스가 선언할 수 있는 선택적 의존성에는 네 가지 종류도 있습니다:
test의존성: 이 릴리스의 자동화된 테스트 스위트를 실행하는 데는 필요하지만, 단지 사용하는 데는 필요하지 않은 다른 릴리스(예:nose2또는pytest)build의존성: 소스에서 이 릴리스의 배포 가능한 바이너리 버전을 빌드하는 데 필요한 다른 릴리스입니다(예:flit또는setuptools).doc의존성: 이 배포판의 문서를 빌드하는 데 필요한 다른 릴리스입니다(예:sphinx빌드 도구).dev의존성: 이 배포판을 작업할 때 필요하지만, 다른 선택적 의존성 범주 중 정확히 하나에 들어맞지 않는 다른 릴리스입니다(예:pylint,flake8).dev의존성은 세 번 나열할 필요 없이 사실상test,build,doc의존성을 합친 것으로도 간주됩니다.
이러한 선택적 범주를 Extras라고 합니다. 네 가지 표준 범주 외에도, 프로젝트는 Extras 필드에 자체적인 사용자 정의 범주를 선언할 수도 있습니다.
다른 엑스트라에 대한 의존성을 내포하는 두 가지 표준 엑스트라 범주도 있습니다:
alldev:test,build,doc,dev엑스트라를 내포합니다.all: 달리 정의되지 않은 경우, 선언된 모든 엑스트라를 내포합니다.
의존성 관리는 PEP 440에 정의된 버전 식별 및 명세 스킴과 PEP 508에 정의된 의존성 명세, 엑스트라, 환경 마커 스킴에 크게 의존합니다.
이 필드는 모두 선택 사항입니다. 배포판이 이 필드를 제공하지 않는 경우, 자동화 도구는 누락된 필드가 “이 배포판에는 해당 없음”을 뜻한다고 가정하여 올바르게 동작해야 합니다(MUST).
의존성을 개발 및 배포 활동에 매핑하기
의존성의 여러 범주는 위에서 식별한 다양한 배포 및 개발 활동을 기준으로 하며, 지정된 활동에 어떤 의존성을 설치해야 하는지를 결정합니다:
- 필수 런타임 의존성:
- 무조건적 의존성
- 필수 빌드 의존성:
build엑스트라dev엑스트라- 빌드 과정의 일부로 배포판의 테스트 스위트를 실행하는 경우, 무조건적 의존성과
test엑스트라도 설치하십시오
- 필수 개발 및 게시 의존성:
- 무조건적 의존성
test엑스트라build엑스트라doc엑스트라dev엑스트라
여러 작업에서 정확히 무엇이 설치되는지 결정할 때는 Extras (optional dependencies)에서 설명하는 표기법을 사용해야 합니다(SHOULD).
설치 도구는 의존성을 충족할 수 없는 경우 오류를 보고해야 하고(SHOULD), 최소한 경고는 반드시 출력해야 하며(MUST), 그럼에도 사용자가 설치를 강제로 진행하도록 허용할 수 있습니다(MAY).
이러한 의존성을 RPM spec 파일에 매핑하는 방법의 개요는 부록 B를 참조하십시오.
엑스트라
의존성 필드에서 조건부 의존성을 정의하는 데 사용할 수 있는 선택적 의존성 집합의 목록입니다. 자세한 내용은 Extras (optional dependencies)를 참조하십시오.
엑스트라 이름은 배포판 이름과 동일한 제약 사항을 따라야 합니다(MUST).
다음 엑스트라 이름은 기본적으로 사용할 수 있으며, 이 필드에 명시적으로 선언해서는 안 됩니다(MUST NOT):
allalldevbuilddevdoctest
예시:
"extras": ["warmup", "tea"]
의존성
이 릴리스를 실제로 실행하는 데 필요한 릴리스 요구 사항 목록입니다.
공개 색인 서버는 이 필드에서 엄격한 버전 일치 절이나 직접 참조를 금지할 수 있습니다.
예시:
"dependencies":
{
"requires": ["SciPy", "PasteDeploy", "zope.interface > 3.5.0"]
},
{
"requires": ["pywin32 > 1.0"],
"environment": "sys_platform == 'win32'"
},
{
"requires": ["SoftCushions"],
"extra": "warmup"
}
]
프로젝트 릴리스를 사용하는 것 자체에 필요한 의존성도 많지만, 어떤 의존성은 특정 플랫폼에서만 필요하거나 릴리스의 특정 선택적 기능이 필요할 때만 필요합니다.
이를 처리하기 위해 릴리스 의존성 지정자는 다음 하위 필드를 갖는 매핑입니다.
requires: 의존성을 충족하는 데 필요한 요구 사항 목록입니다.extra: 함께 요청되고 설치되는 선택적 의존성 집합의 이름입니다. 자세한 내용은 Extras (optional dependencies)를 참조하십시오.environment: 이 의존성들이 필요한 환경을 정의하는 환경 마커입니다. 환경 마커의 문법과 기능은 PEP 508에 정의되어 있습니다.
requires 목록의 개별 항목은 PEP 508에 정의된 의존성 선언 형식을 사용하는 문자열입니다. 다만 예외적으로, 환경 마커는 개별 의존성 선언에 포함되어서는 안 되며(MUST NOT) 대신 별도의 environment 필드에 제공됩니다.
requires는 유일한 필수 하위 필드입니다. 이것이 유일한 하위 필드일 때 해당 의존성은 무조건적이라고 합니다. extra나 environment가 지정되면 해당 의존성은 조건부입니다.
세 필드를 모두 제공할 수도 있으며, 이는 특정 환경에서 지정된 extra가 요청될 때만 해당 의존성이 필요함을 나타냅니다.
자동화 도구는 메타데이터를 직렬화할 때 관련된 의존성 지정자(extra와 environment 값이 같은 지정자)를 여러 요구 사항을 나열하는 하나의 지정자로 반드시 합쳐야 합니다.
이러한 정규화가 요구됨에도 불구하고, 같은 extra 이름이나 환경 마커가 여러 조건부 의존성에 나타날 수 있습니다. 예를 들어 extra 자체가 일부 의존성을 특정 환경에서만 필요로 하는 경우 이런 일이 생길 수 있습니다. 의존성 지정자 목록 안에서 고유해야 하는 것은 extra와 환경 마커의 조합뿐입니다.
여섯 가지 표준 extra 범주를 제외하고, 의존성 지정자에서 참조하는 모든 extra는 이 배포판의 Extras 필드에 반드시 이름이 명시되어야 합니다. 이는 오타를 방지하는 데 도움이 되며, 전체 의존성을 살펴보지 않고도 사용 가능한 extra를 쉽게 파악할 수 있게 해 줍니다.
어떤 extra 정의를 다른 extra의 일부로 재사용하기 위해 프로젝트 릴리스는 자기 자신에 대한 의존성을 선언할 수 있습니다. 이러한 경우 무한 재귀를 피하기 위해 자동화 도구는 프로젝트에서 자기 자신으로 되돌아가는 의존성을 반드시 특별하게 처리해야 합니다.
메타데이터 확장
메타데이터에 대한 확장은 extensions 키 아래의 매핑에 있을 수 있습니다. 키는 반드시 유효한 접두사가 붙은 이름이어야 하며, 값은 반드시 그 자체로 중첩된 매핑이어야 합니다.
두 개의 키 이름은 예약되어 있으며, 아래에 설명된 경우를 제외하고는 확장에서 사용해서는 안 됩니다.
extension_versioninstaller_must_handle
다음 예시는 PEP 459의 python.details 및 python.commands 표준 확장을 보여 줍니다.:
"extensions" : {
"python.details": {
"license": "GPL version 3, excluding DRM provisions",
"keywords": [
"comfy", "chair", "cushions", "too silly", "monty python"
],
"classifiers": [
"Development Status :: 4 - Beta",
"Environment :: Console (Text Based)",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)"
],
"document_names": {
"description": "README.rst",
"license": "LICENSE.rst",
"changelog": "NEWS"
}
},
"python.commands": {
"wrap_console": [{"chair": "chair:run_cli"}],
"wrap_gui": [{"chair-gui": "chair:run_gui"}],
"prebuilt": ["reduniforms"]
},
}
확장 이름은 추가로 게시된 메타데이터를 어떤 방식으로든 활용할 배포판에서 정의합니다.
이름 충돌 가능성을 줄이려면 확장 이름에 해당 확장의 의미를 정의하는 배포 패키지 안의 모듈 이름에 대응하는 접두사를 사용해야 합니다. 이렇게 하면 메타데이터 확장에 대한 권위 있는 문서도 더 쉽게 찾을 수 있습니다.
메타데이터 확장을 통해 개발 도구는 배포의 이후 단계에서 유용할 수 있지만 의존성 해석이나 소프트웨어 빌드에는 필수적이지 않은 정보를 메타데이터에 기록할 수 있습니다.
확장 버전 관리
확장은 반드시 extension_version 키를 사용하여 버전을 지정해야 합니다. 다만 이 키가 생략되면 암묵적 버전은 1.0입니다.
확장 메타데이터를 사용하는 자동화 도구는 extension_version이 자신이 지원하는 최고 버전보다 높으면 경고해야 하며(SHOULD), extension_version의 메이저 버전이 자신이 지원하는 최고 버전보다 높으면 실패해야 합니다(MUST)(PEP 440에서 설명하듯이 메이저 버전은 첫 번째 점 앞의 값입니다).
더 넓은 호환성을 위해, 빌드 도구는 필요한 모든 필드를 포함하는 가장 낮은 메타데이터 버전을 사용하여 확장 메타데이터를 생성하도록 선택할 수 있습니다.
필수 확장 처리
프로젝트는 일부 확장을 올바르게 처리하는 것이 소프트웨어를 올바르게 설치하는 데 필수적이라고 간주할 수 있습니다. 이는 installer_must_handle 필드를 true로 설정하여 나타냅니다. 이 필드를 false로 설정하거나 아예 생략하면, 배포 패키지를 설치할 때 해당 확장을 처리하는 것을 개발자가 필수로 간주하지 않는다는 뜻입니다.
어떤 확장에 대해 installer_must_handle이 true로 설정되어 있는데 설치 도구에 (직접이든 도구별 플러그인 시스템을 통해서든) 그 확장을 처리할 능력이 전혀 없다면, 설치 도구는 반드시 실패해야 합니다.
설치 도구가 wheel 아카이브에서 설치하려다가 이해하지 못하는 필수 확장을 만나면, 완전히 실패하는 대신 소스에서 설치를 시도하는 방식으로 대체할 수 있습니다.
엑스트라(선택적 의존성)
PEP 508에 정의된 대로, 엑스트라는 프로젝트 릴리스의 선택적 기능을 활성화하는 추가 의존성으로, 코드의 try: import optional_dependency ... 블록에 대응하는 경우가 많습니다. 엑스트라는 일반적인 런타임 사용 이외의 활동(테스트, 빌드, 컴포넌트 개발 등)을 위한 의미적 의존성을 나타내는 데에도 사용됩니다.
선택적 의존성이 있든 없든 릴리스를 사용할 수 있도록, 이러한 의존성은 릴리스의 핵심 런타임 의존성과 별도로 나열되며, 다른 프로젝트의 의존성 명세에서든 설치 도구에 명령을 내릴 때든 명시적으로 요청해야 합니다.
선택적 의존성이 있는 배포 패키지의 예:
"name": "ComfyChair",
"extras": ["warmup"]
"dependencies": [
{
"requires": ["SoftCushions"],
"extra": "warmup"
},
{
"requires": ["cython"],
"extra": "build"
}
]
다른 배포 패키지는 의존성을 지정할 때 배포 패키지 이름 뒤의 대괄호 안에 관련 엑스트라 이름을 넣어 추가 의존성을 요구합니다. 하나의 의존성에서 여러 엑스트라를 요청하려면 다음과 같이 배치하여
표준 all 엑스트라에 명시적으로 선언된 항목이 없으면, 통합 도구는 이를 프로젝트가 명시적으로 선언한 모든 엑스트라에 대한 의존성으로 암묵적으로 정의해야 합니다.
표준 alldev 엑스트라에 명시적으로 선언된 항목이 없으면, 통합 도구는 이를 표준 test, build, doc, dev 엑스트라에 대한 의존성으로 암묵적으로 정의해야 합니다.
그러면 전체 의존성 요구 사항 집합은 무조건적 의존성과 요청된 엑스트라들의 의존성을 기반으로 합니다.
의존성 예시(requires 하위 필드만 표시):
"requires": ["ComfyChair"]
-> requires ``ComfyChair`` only
"requires": ["ComfyChair[warmup]"]
-> requires ``ComfyChair`` and ``SoftCushions``
"requires": ["ComfyChair[all]"]
-> requires ``ComfyChair`` and ``SoftCushions``, but will also
pick up any new extras defined in later versions
메타데이터 명세 갱신
메타데이터 명세는 새 PEP나 메타데이터 버전 변경 없이도 내용을 명확히 하기 위해 갱신될 수 있습니다.
기존 필드의 의미를 변경하거나 (확장 메커니즘을 통하지 않고) 새로운 기능을 추가하려면 새 PEP에서 정의한 새 메타데이터 버전이 필요합니다.
부록 A: 레거시 메타데이터 변환 참고 사항
레거시 메타데이터를 메타데이터 2.0으로 변환하기 위한 참조 구현은 다음과 같습니다:
setuptools에bdist_wheel명령을 추가하는 wheel 프로젝트- Warehouse 프로젝트. 이 프로젝트는 차세대 Python 패키지 색인(Python Package Index) 구현으로서 최종적으로 Python 패키징 기관(Python Packaging Authority)으로 이관될 예정입니다
distutils2프로젝트를 위해 만들어진 핵심 패키징 인프라에서 파생된 distlib 프로젝트
Note
이 도구들은 여러 필드를 표준 확장으로 전환한 변경 사항을 아직 반영하지 않았습니다.
깔끔한 변환을 위해 수동 개입이 필요한 예외적인 경우가 일부 있을 것으로 예상되지만, 이 명세는 PyPI에 있는 거의 모든 프로젝트를 완전히 자동으로 변환할 수 있도록 설계되었습니다.
메타데이터 변환(특히 색인 서버 측에서의 변환)은 개발자가 더 새로운 빌드 시스템으로 업그레이드할 때까지 기다리지 않고도 설치 및 분석 도구가 새 메타데이터 형식의 이점을 누리기 시작할 수 있게 하는 데 필요한 단계입니다.
부록 B: 의존성 선언을 RPM SPEC 파일에 매핑하기
이 PEP를 Linux 배포판 패키지에 매핑하는 예로, 엑스트라가 정의되지 않은 예제 프로젝트가 SPEC 파일에서 example과 example-devel이라는 2개의 RPM으로 분할된다고 가정해 봅시다.
무조건 의존성은 “example” RPM의 Requires 의존성으로 매핑됩니다(Linux와 관련된 환경 마커를 SPEC 파일 조건으로 매핑하면 이러한 의존성도 올바르게 처리할 수 있습니다).
build 및 dev extra 의존성은 “example” RPM의 BuildRequires 의존성에 매핑됩니다. RPM에서 %check 섹션을 어떻게 정의했는지에 따라 test extra도 해당 RPM의 BuildRequires 선언에 매핑될 수 있습니다.
dev, test, build, doc 엑스트라에 정의된 의존성 중 Linux와 관련된 모든 의존성은 “example-devel” RPM의 Requires 의존성이 됩니다.
Sphinx와 같은 문서화 도구 체인 의존성은 build extra(예를 들어 빌드된 배포물에 man 페이지가 포함되는 경우)나 doc extra(예를 들어 문서를 Read the Docs나 프로젝트 웹사이트를 통해서만 게시하는 경우) 중 하나에 들어갑니다. 이것만으로도 자동 변환기가 이를 spec 파일의 적절한 의존성에 매핑하기에 충분합니다.
프로젝트가 extra를 정의했다면, 그러한 extra는 의존성 명세의 세부 사항에 따라 적절한 BuildRequires 및 Requires 항목을 갖춘 추가 가상 RPM에 매핑될 수 있습니다. 또는 다른 시스템 패키지 관리자 기능(예: 약한 의존성)에 매핑될 수도 있습니다.
메타데이터 확장 형식은 또한 업스트림 메타데이터를 배포판별 형식으로 수동으로 중복 작성할 필요 없이, 배포판별 힌트를 업스트림 프로젝트 메타데이터에 포함할 수 있는 방법을 제공해야 합니다.
부록 C: PEP 345와의 차이점 요약
- Metadata-Version(메타데이터 버전)은 이제 2.0이며, 버전 변경을 처리하기 위한 의미가 명세되었습니다
- 점점 복잡해지던 임시방편적인 “Key: Value” 형식을 Python 딕셔너리, 문자열, 리스트로 쉽게 표현할 수 있는, 보다 구조화된 JSON 호환 형식으로 대체했습니다.
- 이제 대부분의 필드는 선택 사항이며, 생략된 필드에 더미 데이터를 채워 넣는 것은 명시적으로 금지됩니다
- 명세의 새 버전을 릴리스하지 않고도 그 자리에서 내용을 명확히 하는 것을 명시적으로 허용합니다
- 이제 PEP는 허용되는 내용을 단순히 기술하는 데 그치지 않고, 각 필드가 왜 존재하며 어떻게 사용되도록 의도되었는지를 더 많이 설명하려고 합니다
- 버전 체계가 PEP 386이 아니라 PEP 440을 기반으로 하도록 변경했습니다
- PEP 440에 설명된 소스 레이블 메커니즘을 추가했습니다
- 의존성 선언, extra, 환경 마커를 PEP 508에서 공식적으로 정의했습니다
- 추가로 예약된 extra 이름을 통해 다양한 종류의 의존성을 지원합니다
- 폐기 메커니즘을 갱신했습니다
- 잘 정의된 메타데이터 확장 메커니즘을 도입하고, 의존성 해결에 필요하지 않은 모든 필드를 표준 확장으로 이전했습니다
- Charles Schulz와 Peanuts에게는 송구하지만, 많은 예제를 Python이라는 주제에 더 잘 어울리도록 갱신했습니다 ;)
주요 변경 사항의 근거는 다음 절들에서 설명합니다.
메타데이터 버전(Metadata-Version)의 의미
이제 메이저 및 마이너 버전 증가의 의미 체계가 명시되어 있으며, 이는 PEP 427에서 wheel 형식에 대해 명시한 형식 버전 의미 체계와 같은 모델을 따릅니다. 즉, 마이너 버전 증가는 메이저 버전이 같은 이전 메타데이터 버전만 이해하는 도구가 처리할 때에도 합리적으로 동작해야 하며, 메이저 버전 증가는 기존 도구와 호환되지 않는 변경을 포함할 수 있습니다.
PEP 426 메타데이터는 당연히 이전 메타데이터 명세에 따라 해석될 수 없으므로, 그에 맞게 명세의 메이저 버전 번호를 올렸습니다.
명세의 메이저 버전 번호가 증가할 때마다 배포에는 어느 정도 시간이 걸릴 것으로 예상됩니다. 다른 도구가 새 형식을 안전하게 생성하기 시작하려면 먼저 메타데이터를 소비하는 도구가 업데이트되어야 하거나, 그렇지 않으면 여러 버전의 메타데이터를 병렬로 제공할 수 있도록 sdist와 wheel 형식 및 설치 데이터베이스 정의를 업데이트해야 하기 때문입니다.
기존 도구는 새 메타데이터 표준을 지원하도록 갱신되기 전까지 이 지침을 따르지 않으므로, 새로운 의미 체계는 가상의 2.x -> 3.0 전환에서 처음 적용됩니다. 1.x -> 2.x 전환에서는 도구가 표준 메타데이터 형식의 새 기능(공식 확장 메커니즘 포함)을 사용하여 지정한 동등한 정보에 더해 기존 보조 파일(entry_points.txt 등)도 계속 생성하는 방식을 사용합니다.
JSON 호환 형식으로의 전환
기존의 “Key:Value” 형식은 점점 더 많은 제약이 되었습니다. 파서는 어떤 필드가 두 번 이상 나타날 수 있는지, 어떤 필드가 환경 마커 문법(값과 마커를 구분하는 선택적 ";" 포함)을 지원하는지 알아야 했고, 결국에는 특정 하위 필드 안에 임의의 JSON을 삽입하는 옵션까지 알아야 하는 등 여러 가지 복잡성이 있었습니다.
기존 직렬화 형식은 또한 새로운 설치 훅 API에서 사용하거나, 설치 데이터베이스에 포함할 정보를 제공할 수 있도록 런타임 임포터 API를 향후 확장할 때 사용하기 위해 표준 Python 자료 구조로 쉽게 변환하기에 적합하지 않았습니다.
이에 따라 JSON 호환 메타데이터 형식으로 전환하는 조치를 취했습니다. 이 형식은 API에 더 적합하며, 도구가 올바르게 파싱하고 생성하기도 훨씬 쉽습니다. 메타데이터 파일의 이름을 변경하면 1.x와 2.x 메타데이터를 병렬로 배포하기도 쉬워지므로, 새 메타데이터 형식으로 이전하는 과정의 여러 측면이 크게 단순해집니다.
선호하는 파일 이름으로 특별히 pydist.json을 선택한 것은 이 파일에 기술된 메타데이터가 특정 빌드가 아니라 배포판 전체에 적용된다는 사실과 관련이 있습니다. 향후 특정 대상 환경용 바이너리 배포판을 빌드한 후에만 결정할 수 있는 정보를 담기 위해 추가 메타데이터 형식이 정의될 수 있습니다.
버전 체계 변경
버전 관리 체계에 적용된 여러 변경 사항에 대한 자세한 근거는 PEP 440을 참조하십시오.
소스 레이블
새로운 소스 레이블 지원은 공개 버전 식별자에 대한 제약이 주로 신뢰할 수 있는 자동화된 의존성 분석 도구를 만드는 데 도움을 주기 위해 존재한다는 점을 더 명확히 하기 위한 것입니다. 프로젝트는 의존성 분석 도구가 이해할 수 있는 형태로 변환할 수만 있다면 내부적으로 원하는 버전 관리 체계를 자유롭게 사용할 수 있습니다.
또한 소스 레이블을 사용하면 프로젝트 버전 관리 시스템에서 릴리스를 재구성할 수 있게 해 주는 해시나 태그 이름 같은 버전의 구체적인 세부 정보를 간단하게 기록할 수 있습니다.
배포판의 선택적 의존성 지원
새로운 extras 시스템을 통해 배포판은 선택적 동작을 선언하고, 의존성 필드를 사용하여 특정 의존성이 해당 동작을 지원하는 데에만 필요한 경우를 나타낼 수 있습니다. 이 시스템은 이미 setuptools의 일부로 널리 사용되고 있는 동등한 시스템에서 파생되었으며, 레거시 setuptools 메타데이터의 해당 측면을 새 메타데이터 형식으로 정확하게 표현할 수 있게 해 줍니다.
setuptools와 비교하여 엑스트라 문법에 추가된 사항은 가능한 여러 의존성 조합, 특히 빌드 시스템(테스트 스위트 실행을 선택적으로 지원) 및 개발 시스템과 관련된 의존성 조합을 더 쉽게 표현할 수 있도록 정의되었습니다.
다양한 종류의 의미적 의존성 지원
Extras 시스템을 통해 다섯 가지 종류의 의존성을 구분하면, 프로젝트는 어떤 의존성이 배포판을 개발, 빌드, 테스트 또는 사용하는 데 특별히 필요한지를 선택적으로 나타낼 수 있습니다.
이러한 구분을 업스트림의 Python 전용 메타데이터에서 지원할 때의 장점은, 프로젝트 스스로는 이러한 구분에 신경 쓰지 않더라도 필드를 적절히 분리하는 다운스트림 재배포자의 패치를 더 쉽게 받아들일 수 있다는 점입니다. 시간이 지나면 이를 통해 특정 의존성이 어디에, 언제 설치되는지를 훨씬 더 세밀하게 제어할 수 있을 것입니다.
메타데이터 확장 지원
새로운 확장 기능을 사용하면 메타데이터 네임스페이스의 일부 영역을 다른 프로젝트에 사실상 위임할 수 있으면서도, 특정 확장을 지원하지 않는 배포 도구가 쉽게 처리할 수 있도록 표준적인 전체 메타데이터 형식이 유지됩니다.
또한 이 기능은 새로운 build extra와 결합하여 배포판이 선택한 확장을 처리하는 방법을 실제로 알고 있는 도구에 의존할 수 있게 해 주며, 새로운 extras 메커니즘 전반과도 잘 어울려 특정 확장에 대한 지원을 선택적 기능으로 제공할 수 있게 해 줍니다.
확장의 향후 활용 가능성으로는 다른 프로젝트용 플러그인 선언이나 Linux 시스템 패키지로의 자동 변환을 위한 힌트 등이 있습니다.
확장을 필수로 선언하는 기능은 주로 메타데이터 훅 확장의 정의를 메타데이터 2.0 명세가 처음 채택된 이후 얼마간의 시점까지 미룰 수 있도록 하기 위해 포함되었습니다. 릴리스가 설치를 성공적으로 완료하기 위해 postinstall 훅을 실행해야 한다면, 이전 버전의 도구는 wheel 파일로 설치한 뒤 예상된 postinstall 훅을 실행하지 못하는 대신 소스로부터 설치하는 방식으로 대체해야 합니다.
부록 D: 연기된 기능
새 메타데이터 표준으로 이전하는 작업에 노력을 더 잘 집중하기 위해, 잠재적으로 유용한 몇 가지 기능을 의도적으로 연기했습니다. 이 기능들은 모두 새 메타데이터에 있으면 좋을 만한 정보를 반영하지만, 메타데이터 2.0이 이미 지원하는 사용 사례를 깨뜨리지 않고도 메타데이터 확장을 통해서나 메타데이터 2.1에서 쉽게 추가할 수 있습니다.
pypi, setuptools, pip, wheel, distlib 프로젝트가 메타데이터 2.0의 생성과 소비를 지원하게 되면, 이러한 추가 기능의 일부 또는 전부를 포함하는 메타데이터 2.1의 작성을 다시 검토할 수 있습니다.
표준 확장
레거시 메타데이터 시스템이 제공하던 정보 중 일부는 PEP 459에 정의된 표준 확장으로 옮겨졌습니다.
이렇게 하면 해당 확장의 세부 사항이 모두 확정되기 전이라도 핵심 의존성 메타데이터를 더 쉽게 소비할 수 있는 형식으로 게시하는 작업을 진행할 수 있습니다.
프로젝트 폐기, 이름 변경 및 병합 처리 개선
이 PEP의 이전 초안에는 프로젝트 폐기, 이름 변경 및 병합을 더 견고하게 자동으로 알리고 추적하기 위한 새로운 Provides 필드와 Obsoleted-By 필드가 포함되어 있었습니다.
이는 의존성 관리 시스템의 필수 기능이 아니므로, 향후 가능한 메타데이터 확장으로 무기한 연기되었습니다.
MIME 타입 등록
PEP가 승인된 후 어느 시점에, 다음 MIME 타입 등록 요청을 IANA에 제출할 수 있습니다:
application/vnd.python.pydist+json
개별 하위 형식을 각각 등록하는 대신 PSF의 이름으로 vnd.python 네임스페이스만 등록하는 것도 가능할 수 있습니다.
환경 마커의 문자열 메서드
환경 마커에서 최소한 “.startswith”와 “.endswith” 문자열 메서드를 지원하면 일부 조건을 더 자연스럽게 작성할 수 있습니다. 예를 들어, "sys.platform.startswith('win')"은 Windows 전용 의존성을 표시하는 조금 더 직관적인 방법입니다. cygwin 때문에 "'win' in sys.platform"은 올바르지 않으며, 64비트 Windows가 여전히 win32로 표시된다는 사실도 상당히 이상하기 때문입니다.
부록 E: 거부된 기능
다음 기능들은 명시적으로 검토되었으나, 표현력에서 얻는 이득에 비해 추가되는 복잡성이 지나치게 크다는 이유로 거부되었습니다.
조건부 의존성과 무조건부 의존성을 위한 별도의 목록
이 PEP의 이전 버전에서는 조건부 의존성과 무조건부 의존성에 별도의 목록을 사용했습니다. 이는 자동화 도구에서 처리하기 번거로운 것으로 드러났고, 이를 제거하자 PEP와 메타데이터 스키마도 상당히 짧아졌습니다. 이는 실제로 설명하기도 더 어려웠다는 것을 시사합니다.
의미별 의존성을 위한 별도의 목록
이 PEP의 이전 버전에서는 테스트, 빌드, 문서화, 개발 의존성에 extras 시스템 대신 별도의 필드를 사용했습니다. 이는 자동화 도구에서 처리하기 번거로운 것으로 드러났고, 이를 제거하자 PEP와 메타데이터 스키마도 상당히 짧아졌습니다. 이는 실제로 설명하기도 더 어려웠다는 것을 시사합니다.
지나치게 정밀한 의존성 선언에 대한 제약 도입
이 PEP의 이전 버전에서는 게시된 릴리스에서 지나치게 엄격한 의존성 선언을 부적절하게 사용하는 것을 어렵게 만드는 제약을 도입하려고 시도했습니다. distutils-sig에서의 논의 결과, 이는 상호 운용성 명세 계층에서 직접 다룰 만큼 심각한 문제가 아니며, 향후 문제가 된다면 프로젝트가 공개 Python 패키지 색인에 업로드되는 시점에서 다루는 것이 더 낫다는 결론에 도달했습니다.
배포 이름에서 밑줄 사용 금지
Debian은 실제로 이름에 밑줄을 허용하지 않지만, 유효한 Python 식별자를 Python 배포 이름으로 사용하는 관행이 일반적이라는 점을 고려하면 이 명세에서 그렇게 제한하는 것은 지나치게 엄격해 보입니다. 밑줄을 하이픈으로 변환하는 Debian 측 정책은 충분히 쉽게 구현할 수 있어 보입니다(그리고 하이픈과 밑줄을 동등하게 간주해야 한다는 요구 사항 덕분에 그렇게 하더라도 이름 충돌이 발생하지 않습니다).
배포 이름에서 유니코드 사용 허용
이 PEP는 임의의 유니코드 식별자를 허용하는 Python 3의 길을 의도적으로 따르지 않습니다. 소프트웨어 배포 사용 사례에서는 그렇게 할 경우의 보안 영향이 훨씬 더 심각하기 때문입니다(단순한 코드 난독화보다 훨씬 더 흥미로운 공격 벡터를 열어 줍니다).
또한 기존 도구들은 이름을 ASCII로 제한해야만 제대로 동작하며, 이를 바꾸려면 체인에 있는 모든 자동화 도구에 많은 작업이 필요합니다.
(먼) 미래의 어느 시점에 이 문제를 다시 검토하는 것이 합리적일 수도 있지만, 더 일반적인 유니코드 식별자 지원까지 더하지 않더라도 더 신뢰할 수 있는 소프트웨어 배포 시스템을 구축하는 것만으로도 충분히 어려운 일입니다.
소스 레이블에 대한 의존
소스 레이블에 대한 의존성을 표현하는 메커니즘은 없습니다. 소스 레이블은 프로젝트 내부 참조용으로만 메타데이터에 포함됩니다. 대신 의존성은 공개 버전이나 직접 URL 참조로 표현해야 합니다.
대체 의존성
이 PEP의 이전 초안에서는 의존성을 충족하는 방법이 여러 가지 있음을 나타내기 위해 의존성 명세에서 일반적인 문자열 대신 리스트를 허용하는 방안을 검토했습니다.
개별 의존성 중 하나 이상이 이미 사용 가능하다면 전체 의존성이 충족된 것으로 간주하고, 그렇지 않으면 첫 번째 항목을 의존성 집합에 추가하는 방식이었습니다.
대체 의존성 명세 예:
["Pillow", "PIL"]
["mysql", "psycopg2 >= 4", "sqlite3"]
그러나 제시된 예는 어느 것도 특별히 설득력이 없습니다. Pillow/PIL 방식의 포크는 흔하지 않으며, 데이터베이스 드라이버 사용 사례는 SQL Alchemy가 정의하는 “지원 데이터베이스 드라이버” 메타데이터 확장으로 처리하는 편이 더 낫다고 볼 수 있기 때문입니다. 이 방식에서는 프로젝트가 SQL Alchemy에 의존하고, 업스트림 프로젝트가 호환성을 검사한 데이터베이스 드라이버를 확장에 선언합니다.
환경 마커에서의 호환 릴리스 비교
PEP 440은 환경 마커의 python_version 및 python_full_version과 함께 사용하면 유용할 수도 있는 풍부한 버전 비교 문법을 정의합니다. 그러나 전체 문법을 허용하면 환경 마커가 더 이상 Python의 부분 집합이 아니게 되고, 비교 중 일부만 허용하면 처리해야 할 특수한 경우가 또 하나 생기게 됩니다.
환경 마커는 메타데이터 구조상 상위 수준의 “or”가 암시되는 경우에만 사용되므로, 이러한 비교가 유용한 드문 경우에는 특정 Python 버전에 대한 비교를 여러 개 사용하도록 요구하는 편이 더 간단해 보입니다.
조건부 provides
개정된 메타데이터 설계에서는 런타임 기능이나 환경에 따른 조건부 “provides”를 별도의 “may_provide” 필드에 넣게 됩니다. 그러나 그렇게 해야 하는 사용 사례가 있는지 분명하지 않으므로, 누군가 설득력 있는 사용 사례를 제시하지 않는 한 이 아이디어는 기각됩니다(그렇더라도 이 아이디어는 빨라야 메타데이터 2.1에서 다시 검토됩니다).
참고 문헌
이 문서는 메타데이터 형식의 버전 2.0을 명세합니다. 버전 1.0은 PEP 241에 명세되어 있습니다. 버전 1.1은 PEP 314에 명세되어 있습니다. 버전 1.2는 PEP 345에 명세되어 있습니다.
표준화된 버전 체계를 처음 시도한 내용과 그러한 표준이 필요한 이유는 PEP 386에서 확인할 수 있습니다.
Copyright
This document has been placed in the public domain.