PEP 301 – Distutils를 위한 패키지 색인과 메타데이터
- Author:
- Richard Jones <richard at python.org>
- Status:
- Final
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 24-Oct-2002
- Python-Version:
- 2.3
- Post-History:
- 08-Nov-2002
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Distutils 패키징 시스템 [1]에 대한 몇 가지 확장을 제안합니다. 이러한 개선 사항에는 중앙 패키지 색인 서버, 패키지 정보를 색인에 제출하기 위한 도구, 그리고 Trove [2] 정보를 포함하도록 하는 패키지 메타데이터 확장이 포함됩니다.
이 PEP는 패키지 의존성 문제를 다루지 않습니다. 또한 PEP 243에서 설명하는 패키지 저장과 다운로드도 다루지 않습니다. PEP 262에서 설명하는 로컬 패키지 데이터베이스를 제안하는 것도 아닙니다.
Vaults of Parnassus [3], CPAN [4], PAUSE [5] 같은 기존 패키지 저장소를 이 분야(필드)의 선행 사례로 조사할 것입니다.
근거
Python 프로그래머들은 오랫동안 자신이 사용할 수 있는 기존 모듈과 시스템을 찾아내는 간단한 방법을 필요로 해 왔습니다. 다른 언어에 이러한 시스템이 존재한다는 점이 해당 언어들의 인기에 크게 기여했다고 볼 수도 있습니다. Catalog-SIG가 존재하고 그곳에서 많은 논의가 이루어졌다는 사실은 이러한 필요성을 인식하는 사용자가 많다는 것을 보여 줍니다.
Python에 Distutils 패키징 시스템이 도입되면서 공유 가능한 코드를 배포하는 과정이 단순해졌고, 패키지 메타데이터를 수집하는 메커니즘도 포함되었지만, 메타데이터를 패키지와 함께 실어 보내는 것 외에는 별다른 일을 하지 않았습니다.
색인에 대한 인터페이스는 python.org 도메인에서 호스팅되어야 하며, 이를 통해 기존 카탈로그 구축 시도들에는 없는 정당성을 갖추게 됩니다.
카탈로그에 정보를 제출하기 위한 인터페이스는 가능한 한 단순해야 하며, 대부분의 사용자에게는 한 줄짜리 명령이면 충분하기를 바랍니다.
패키지 의존성 문제는 그러한 시스템의 복잡성 때문에 다루지 않습니다. PEP 262가 그러한 시스템을 제안하고 있지만, 이 글을 쓰는 시점에 해당 PEP는 아직 완성되지 않았습니다.
패키지 보급(중앙 서버에 저장하는 것) 문제는 저장 공간과 대역폭의 가용성에 대한 가정이 필요한데, 저는 그러한 가정을 할 수 있는 입장이 아니므로 다루지 않습니다. 아직 개발 중인 PEP 243이 이 문제들과 그 밖의 많은 문제를 다루고 있습니다. 이 제안은 PEP 243의 제안과 호환되며 이를 보완하는 것으로 간주됩니다.
명세
명세는 Web Interface, Distutils register Command, Distutils Trove Classification의 세 부분으로 구성됩니다.
웹 인터페이스
웹 인터페이스는 단순한 저장소 위에 구현됩니다. 이 인터페이스는 python.org 도메인을 통해 직접 또는 packages.python.org로 제공됩니다.
저장소에는 모든 메타데이터 필드에 대한 열이 있습니다. (name, version) 쌍이 고유 키로 사용됩니다. 기존 (name, version)에 대해 추가로 제출하면 update 연산이 수행됩니다.
웹 인터페이스는 다음 명령/인터페이스를 구현합니다:
- index
- 알려진 패키지 목록을 보여 주며, 선택적으로 필터링할 수 있습니다. 추가 HTML 페이지인 search는 색인 보기를 사용자 지정하는 데 쓰이는 양식을 사용자에게 제공합니다. 색인에는 Trove 인터페이스 설계 4.3절에 제시된 것과 같은 탐색 인터페이스가 포함됩니다. 결과는 페이지로 나뉘고 알파벳순으로 정렬되며, 가장 최신 버전만 표시됩니다. 가장 최신 버전 정보는 Distutils LooseVersion 클래스를 사용하여 결정합니다.
- display
- 패키지에 관한 정보를 표시합니다. 모든 필드는 일반 텍스트로 표시됩니다. “url”(또는 “home_page”) 필드에는 하이퍼링크가 걸립니다.
- submit
- 패키지에 관한 메타데이터를 POST로 제출받습니다. “name”과 “version” 필드는 색인의 항목을 고유하게 식별하므로 필수입니다. Submit은 새 항목을 만들지 기존 항목을 갱신할지 자동으로 결정합니다. 메타데이터는 적절한 경우 올바른지 검사하며, 특히 Trove 판별자는 허용된 집합과 비교합니다. 갱신하면 새로 제출된 정보를 바탕으로 패키지에 관한 모든 정보가 갱신됩니다.
Distutils를 사용하지 않는 사람들이 수동으로 제출하고 갱신할 수 있도록 제출/편집 양식도 제공됩니다.
- submit_pkg_info
- PKG-INFO 파일의 POST 제출을 받아 submit 인터페이스와 동일한 함수를 수행합니다.
- user
- 색인에 새 사용자를 등록합니다. 사용자 이름, 비밀번호, 이메일 주소가 필요합니다. 비밀번호는 색인 데이터베이스에 SHA 해시로 저장됩니다. 사용자 이름이 데이터베이스에 이미 있는 경우:
- 유효한 HTTP Basic 인증이 제공되면 제출된 정보로 비밀번호와 이메일 주소를 갱신하거나,
- 유효한 인증이 제공되지 않으면 해당 로그인 이름이 이미 사용 중이라고 사용자에게 알립니다.
등록은 다음 세 단계로 이루어집니다:
- 사용자가 Distutils register 명령이나 웹을 통해 세부 정보를 제출하고,
- 색인 서버가 등록 확인을 위해 방문할 URL과 무작위 일회용 키를 담은 이메일을 사용자의 이메일 주소로 보내고,
- 사용자가 키가 포함된 URL을 방문하여 등록을 확인합니다.
- roles
- 사용자의 역할(Role) 할당을 변경하는 인터페이스입니다.
- password_reset
- 제공된 이메일 주소를 키로 사용하여 사용자의 비밀번호를 재설정하고, 새 비밀번호를 담은 이메일을 사용자에게 보냅니다.
submit 명령에는 HTTP Basic 인증이 필요하며, 가급적 HTTPS 연결을 통해 인증하는 것이 좋습니다.
서버 인터페이스는 표준 HTTP 응답 코드 중 일부를 사용하여 명령의 성공 또는 실패를 알립니다:
| 코드 | 의미 | register 명령에서의 의미 |
|---|---|---|
| 200 | OK | 모든 작업이 정상적으로 처리되었습니다 |
| 400 | Bad request | 제출용으로 제공된 데이터의 형식이 잘못되었습니다 |
| 401 | Unauthorised | 제공된 사용자 이름 또는 비밀번호가 올바르지 않습니다 |
| 403 | Forbidden | 사용자에게 패키지 정보를 갱신할 권한이 없습니다(소유자 또는 유지 관리자가 아님) |
사용자 역할
사용자에게는 세 가지 역할을 부여할 수 있습니다:
- 소유자(Owner)
- 패키지 이름을 소유하며, 해당 이름에 대해 유지 관리자 역할을 부여할 수 있습니다. 패키지에 대한 정보를 처음으로 등록한 사용자가 해당 패키지 이름의 소유자로 간주됩니다. 필요한 경우 관리자 사용자가 이를 변경할 수 있습니다. 해당 패키지 이름에 대한 갱신 사항을 제출할 수 있습니다.
- 유지 관리자
- 특정 패키지 이름에 대한 정보를 제출하고 갱신할 수 있습니다.
- 관리자(Admin)
- 소유자 역할을 부여하고 사용자 세부 정보를 편집할 수 있습니다. 특정 패키지 이름에 한정되지 않습니다.
색인 저장소(스키마)
색인은 관계형 데이터베이스 테이블 집합에 저장됩니다:
- 패키지
- 패키지 이름을 나열하고 패키지 수준 메타데이터(현재는 안정 릴리스 버전뿐)를 보관합니다.
- releases
- 각 패키지는 릴리스된 패키지의 버전마다 releases에 항목을 하나씩 가집니다. 한 행에는 패키지의 PKG-INFO 파일에 주어진 정보의 대부분이 담깁니다. 각 패키지(name, version)마다 하나의 행이 있습니다.
- trove_discriminators
- Trove 판별자 텍스트를 나열하고 각각에 고유한 ID를 부여합니다.
- release_discriminators
- 각 항목은 패키지(name, version)를 discriminator_id에 매핑합니다. 판별자 집합이 릴리스마다 바뀔 수 있으므로 패키지가 아닌 릴리스에 매핑합니다.
- journals
- 색인에 있는 패키지 정보의 변경 사항에 관한 정보를 보관합니다. packages, releases, roles, release_discriminators 테이블의 변경 사항은 여기에 패키지 name과, 변경이 특정 릴리스에 해당하는 경우에는 version으로 기록됩니다.
- users
- 사용자 데이터베이스(사용자 이름, 이메일 주소, 비밀번호)를 보관합니다.
- roles
- user_name과 role_name을 package_name에 매핑합니다.
추가 테이블인 rego_otk는 등록 중에 생성되는 일회용 키(One Time Key)를 보관하며, 색인 자체의 범위에서는 중요하지 않습니다.
Distutils register 명령
패키지 메타데이터를 중앙 색인에 게시하는 추가 Distutils 명령인 register가 구현됩니다. register 명령은 사용자 등록을 자동으로 처리하며, 사용자에게는 다음 세 가지 선택지가 제시됩니다:
- 로그인하여 패키지 정보 제출
- 새 패키지 작성자로 등록
- 비밀번호 알림 이메일 발송
$HOME 환경 변수가 설정된 시스템에서는 종료 시 사용자에게 사용자 이름/비밀번호를 $HOME 디렉터리의 .pypirc 파일에 저장할지 묻습니다.
패키지 항목의 변경 알림은 해당 패키지에 관한 정보를 제출한 모든 사용자에게 발송됩니다. 즉, 최초 제출자와 이후의 모든 갱신자에게 발송됩니다.
register 명령에는 데이터를 실제로 커밋하지 않고 색인에 시험 제출을 수행하는 --verify 옵션이 포함됩니다. 색인은 평소처럼 제출 검증 검사를 수행하고, 일반 제출 시 보고했을 오류를 모두 보고합니다. 이는 Trove 판별자가 올바른지 검증하는 데 유용합니다.
Distutils Trove 분류
Trove의 discrimination 개념은 새 속성 “classifiers”를 통해, 패키지 작성자가 사용할 수 있는 메타데이터 집합에 추가됩니다. 분류자 목록은 웹을 통해 제공되며, 다음과 같이 패키지에 추가됩니다:
setup(
name = "roundup",
version = __version__,
classifiers = [
'Development Status :: 4 - Beta',
'Environment :: Console',
'Environment :: Web Environment',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Python Software Foundation License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: Python',
'Topic :: Communications :: Email',
'Topic :: Office/Business',
'Topic :: Software Development :: Bug Tracking',
],
url = 'http://sourceforge.net/projects/roundup/',
...
)
더 형식을 갖춘 Python 구조를 쓰면 중첩이 깊어지므로, 분류 항목에는 문자열을 사용하기로 결정했습니다.
원래 Trove 명세는 분류 네임스페이스를 슬래시(“/”)로 구분하도록 했지만, 안타깝게도 이 방식은 이름에 슬래시가 들어간 많은 항목(예: “OS/2”)과 충돌합니다. SourceForge와 FreshMeat가 구현한 이중 콜론 방식(” :: “)은 이 제약을 피해 갑니다.
모듈 색인의 분류 값 목록은 FreshMeat와 SourceForge의 목록을 (그들의 허락을 받아) 병합한 것입니다. 이 목록은 웹 인터페이스와 register 명령의 --list-classifiers 옵션 양쪽에서 텍스트 목록으로 제공되며, 이 목록을 setup.py 파일에 복사해 넣을 수 있습니다. register 명령의 --verify 옵션은 classifiers 값을 서버의 목록과 대조하여 검사합니다.
안타깝게도 “classifiers” 속성을 추가하면 하위 호환성이 깨집니다. 이 속성을 사용하는 setup.py 파일은 Python 2.1.3에서 동작하지 않습니다. Python 2.2의 버그 수정 릴리스(2.2.3일 가능성이 가장 높음)에서 setup() 명령의 인자 검사가 완화되어, 실제로 사용되지 않더라도 새 키워드를 허용하게 되기를 기대합니다. 진행을 막는 오류보다는 경고를 내는 편이 바람직합니다. 패키지가 2.2.3 또는 2.3 이전의 Python 버전과 호환된다고 알리는 경우에는 새 키워드 사용을 자제해야 합니다.
PKG-INFO에서 classifiers 목록의 항목은 각각 개별 Classifier: 항목으로 나타납니다:
Name: roundup
Version: 0.5.2
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console (Text Based)
.
.
Classifier: Topic :: Software Development :: Bug Tracking
Url: http://sourceforge.net/projects/roundup/
구현
서버는 다음 주소에서 이용할 수 있습니다:
코드는 다음 SourceForge 프로젝트에서 받을 수 있습니다:
register 명령은 Python 2.3에 통합되었습니다.
거부된 제안
원래 색인 서버는 (PEP 243에서 영감을 받아) 사용자 정의 헤더를 반환할 예정이었습니다:
- X-Pypi-Status
- “success” 또는 “fail” 중 하나입니다.
- X-Pypi-Reason
- 실패 이유에 대한 설명이며, 성공한 경우에는 추가 정보입니다.
그러나 이 방식은 사용하기에 좋지 않다는 지적이 있었습니다 [6].
참고 문헌
Copyright
This document has been placed in the public domain.
Acknowledgements
Anthony Baxter, Martin v. Loewis and David Goodger for encouragement and feedback during initial drafting.
A.M. Kuchling for support including hosting the second prototype.
Greg Stein for recommending that the register command interpret the HTTP response codes rather than custom X-PyPI-* headers.
The many participants of the Distutils and Catalog SIGs for their ideas over the years.