PEP 829 – 패키지 시작 구성 파일
- Author:
- Barry Warsaw <barry at python.org>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Created:
- 31-Mar-2026
- Python-Version:
- 3.15
- Post-History:
- 01-Apr-2026, 13-Apr-2026, 15-Apr-2026
- Resolution:
- 24-Apr-2026
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 패키지가 Python의 시작 프로세스에 영향을 미치는 방식을 변경합니다. 인터프리터 시작 중 site.py 파일이 구문 분석하고 실행하여 이전에 제어하던 이러한 레거시 .pth 파일은 sys.path를 확장하고 사용자 코드의 첫 번째 줄로 제어가 전달되기 전에 패키지 초기화 코드를 실행하는 데 사용됩니다.
이 PEP는 다음을 제안합니다.
.pth파일의import줄을.start파일의 진입점 사양(즉,pkg.mod:callable)으로 대체합니다.- 일치하는
.start파일이 있으면 일치하는.pth파일에서import줄 처리가 비활성화됩니다. .pth파일의sys.path확장 기능은 유지됩니다.
.pth 파일의 import 줄 지원은 점진적으로 제거됩니다.
- 처음 3년(예상되는 Python 3.15, 3.16 및 3.17) 동안에는 일치하는
.start파일이 있는 경우를 예외로.pth파일의import줄 처리가 유지됩니다. - 그 다음 2년(예상되는 Python 3.18 및 3.19) 동안에는
.pth파일의import줄이 자동으로 무시됩니다. - 그 이후(예상되는 Python 3.20 이상)에는
.pth파일에import줄이 존재한다는 경고가 생성됩니다.
동기
Python의 .pth 파일(시작 시 Lib/site.py가 처리함)은 두 가지 기능을 지원합니다.
- 확장
sys.path– 이 파일의 줄 중 주석 및import로 시작하는 줄을 제외한 줄은sys.path에 추가할 디렉터리를 지정합니다. 상대 경로는 암묵적으로 site-packages 디렉터리를 기준으로 합니다. - 임의 코드 실행 –
import(또는import\\t)로 시작하는 줄은 소스 문자열을exec()에 전달하여 즉시 실행됩니다.
두 기능 모두 유효한 사용 사례가 있지만, import 줄 기능이 가장 문제가 되는 이유는 다음과 같습니다.
- 코드 실행이 구현의 부작용입니다.
import로 시작하는 줄은 여러 문을 세미콜론으로 구분하여 확장할 수 있습니다. 실행할 모든 코드가 같은 줄에 나타나기만 하면.pth파일이 처리될 때 모두 실행됩니다. import줄은 인터프리터 시작 중exec()을 사용하여 실행되므로 광범위한 공격 표면이 열립니다.- Python 패키징에서 이미 확립된 패턴인 진입점이라는 명시적 개념이 없습니다. 시작 시 코드 실행과 초기화가 필요한 패키지는 진입점을 명시적으로 선언하는 대신
import줄을 악용합니다.
사양
이 PEP는 다음을 제안합니다.
<name>.pth파일 형식은 유지하되, 3년 동안import줄 처리를 사용 중단하고 그 이후에는 이러한 줄을 허용하지 않습니다.<name>.pth파일의 현재sys.path확장 기능은 변경 없이 유지합니다. 구체적으로 절대 경로는 있는 그대로 사용하고, 상대 경로는.pth파일이 있는 디렉터리를 기준으로 합니다.<name>.start라는 새로운 파일 형식이 추가되며,pkgutil.resolve_name()인자의 “콜론 형식”을 따르는 진입점의 이름을 지정합니다.- 사용 중단 예고 기간 동안
<name>.pth파일과 일치하는<name>.start파일이 존재하면,<name>.pth파일의import줄 실행이 비활성화되고<name>.start파일의 엔트리 포인트가 대신 사용됩니다. 이를 통해 이 PEP를 지원하는 Python 버전과 지원하지 않는 이전 버전에 걸쳐 마이그레이션 경로를 제공할 수 있습니다. 이 경우import줄에 대한 경고는 출력되지 않습니다.사용 중단 예고 기간 동안 일치하는
<name>.start파일이 없는 모든<name>.pth파일은 전자에 대한 처리가 변경되지 않지만, Python에-v(verbose) 플래그를 지정하면import줄에 대한 경고가 발행됩니다.사용 중단 예고 기간이 끝난 후에는 일치하는
<name>.start파일의 존재 여부와 관계없이<name>.pth파일의import줄이 무시되고 경고가 발행됩니다.구체적인 마이그레이션 지침은 이 내용을 가르치는 방법 섹션을 참조하십시오.
<name>.pth 파일과 <name>.start 파일은 현재의 .pth 파일과 마찬가지로 site.py 모듈에서 처리됩니다. 이는 disabling site.py processing을 -S로 비활성화하면 두 파일의 처리가 모두 비활성화된다는 의미입니다.
site.py 시작 코드는 다음과 같은 명시적 단계로 나뉩니다.
<name>.pth파일을 찾고(파일 이름 지정 및 검색에서 자세한 내용을 참조하십시오) 파일 이름의 알파벳순으로 정렬합니다.<name>.pth파일을 정렬된 순서로 구문 분석하고, 모든 경로 확장자의 전역 목록을 유지하면서 파일별 순서와 항목이 나타나는 순서를 보존합니다. 중복 항목은 무시됩니다.- 사용 중단 예고 기간 동안
<name>.pth파일에서 찾은import줄을 수집합니다. 이러한 줄의 처리는<name>.start파일 검색이 끝난 후로 연기됩니다. - 향후 확장: 경로 확장자 목록에 global policy filter를 적용합니다.
- 보존된 전역 순서에 따라 경로 확장자를
sys.path에 추가합니다. - 모든
<name>.start파일을 나열하고(파일 이름 지정 및 검색에서 자세한 내용을 참조하십시오) 파일 이름의 알파벳순으로 정렬합니다.이전에 검색한
<name>.pth파일과 일치하는<name>.start파일에 대해서는, 일치하는 해당<name>.pth파일의 모든import줄을 폐기합니다. 자세한 내용과 근거는 이 내용을 가르치는 방법 섹션을 참조하십시오. <name>.start파일을 정렬된 순서로 구문 분석하고, 모든 엔트리 포인트의 전역 목록을 유지하면서 파일별 순서와 항목이 나타나는 순서를 보존합니다. 중복 항목은 무시되지 않습니다.- 향후 확장: 엔트리 포인트 목록에 global policy filter를 적용합니다.
- 보존된 순서의 각 엔트리 포인트에 대해
pkgutil.resolve_name()을 사용하여 해당 엔트리 포인트를 호출 가능 객체로 해석합니다. 인수 없이 엔트리 포인트를 호출하고 반환값은 폐기합니다. 해석된 객체는 호출하기 전에 호출 가능 여부를 검사하지 않으므로, 그 결과 발생할 수 있는TypeError가 보고됩니다.
<name>.pth 파일과 <name>.start 파일 모두에서 주석 줄(즉, 공백이 아닌 첫 문자가 #로 시작하는 줄)과 빈 줄은 무시됩니다. 그 밖의 구문 분석 오류가 발생하면 해당 줄은 무시됩니다.
엔트리 포인트 구문
pkgutil.resolve_name()을 사용하여 엔트리 포인트 사양을 호출 가능 객체로 해석합니다. 그러나 Python 3.14 이하에서는 이 함수가 문서에서 의사 정규 표현식으로 설명된 다음 두 형식을 허용합니다.
W(.W)*- 콜론이 없는 형식W(.W)*:(W(.W)*)?- 선택적 호출 가능 객체 접미사가 있는 콜론 형식
이 PEP는 pkg.mod:callable 형식의 진입점만 허용하고 호출 가능 객체가 지정되도록 제안합니다. 자세한 논의는 open issues를 참조하십시오.
파일 이름 지정 및 검색
- 패키지는
<name>.pth및<name>.start형식의 파일을 0개 이상 선택적으로 설치할 수 있습니다.<name>접두사는 임의이며 패키지 이름이나 서로 일치할 필요는 없지만, 다른 조건이 모두 같다면 명확성을 위해 패키지 이름과 일치하도록 권장합니다. 인터프리터는 접두사에 대한 제약을 적용하지 않습니다. - 파일은 알파벳순으로 처리됩니다.
<name>.start파일은 현재<name>.pth파일이 발견되는 동일한 site-packages 디렉터리에 있습니다.<name>.pth위치는 그대로 유지됩니다.<name>.start파일의 검색 규칙은 현재<name>.pth파일의 검색 규칙과 동일합니다. 단일.로 시작하는 파일 이름(예:.start)과 OS 수준의 숨김 속성(UF_HIDDEN,FILE_ATTRIBUTE_HIDDEN)이 있는 파일은 제외됩니다.
오류 처리
구문 분석 중에는 일반적으로 오류를 건너뛰며 Python에 -v (verbose) 플래그를 지정한 경우에만 보고합니다. 현재 .pth 파일과 달리, 오류가 발생해도 처리가 파일 전체에 대해 중단되지는 않습니다.
<name>.pth또는<name>.start파일을 열거나 읽을 수 없으면 해당 파일을 건너뛰고 다음 파일로 처리를 계속합니다.- 잘못된 진입점 지정은 건너뜁니다.
실행 중 발생한 오류는 sys.stderr에 출력하고 처리를 계속합니다.
- 유효하지 않거나 존재하지 않는 경로를 가리키는 모든
sys.path확장 디렉터리는 무시하고 다음 경로 항목으로 처리를 계속합니다. - 진입점 실행 중 발생한 예외는 출력하고 다음 진입점으로 처리를 계속합니다.
인코딩
<name>.start 파일은 utf-8-sig로 반드시 인코딩되어야 하며, 이는 선택적 바이트 순서 표시가 있는 UTF-8이어야 합니다.
<name>.pth 파일도 가능하면 utf-8-sig로 인코딩해야 합니다. 현재 <name>.pth 파일이 utf-8-sig로 인코딩되지 않은 경우 디코딩은 현재 로캘로 대체되지만, 이 PEP는 해당 지원을 5년 동안 사용 중단하며, 그 후에는 <name>.pth 파일도 반드시 utf-8-sig로 인코딩되어야 합니다.
향후 개선
.pth 및 .start 파일의 2단계 처리를 도입하면 향후 개선을 구현할 수 있으며, 이를 통해 일부 전역 사이트 정책을 적용하여 sys.path 확장과 진입점 실행을 더욱 세밀하게 제어할 수 있습니다. 구문 분석 후 정책을 적용하여 여러 기준에 따라 경로 확장 또는 진입점을 허용하거나 거부할 수 있다고 생각해 볼 수 있습니다. 이러한 기준으로는 확장을 지정하는 데 사용된 <name> 접두사, 경로 위치 또는 진입점이 정의된 모듈 등이 있습니다.
이 PEP는 이러한 정책 메커니즘의 설계를 의도적으로 향후 사양에 맡깁니다.
근거
이 PEP의 이전 버전에서는 메타데이터, 경로 확장 목록 및 진입점 목록을 테이블로 지정하는 통합된 <name>.site.toml 파일의 사용을 제안했습니다. PEP 작성자와 여러 토론 참가자는 이 구조화된 접근 방식을 선호했지만, 일부 반대자들은 TOML 파일이 이 제안에 비해 지나치게 복잡하다는 의견을 표명했습니다. PEP 작성자는 TOML 파일의 처리 오버헤드가 무시할 수 있는 수준이며, 구조화된 접근 방식이 가독성과 향후 확장성에 유용하다고 생각합니다. 반대자들은 YAGNI로 맞섰습니다.
두 파일 방식은 이전 .pth 파일 처리 방식에 대한 간단한 점진적 개선입니다. 첫 번째 개선은 import 줄을 exec()를 통해 실행하는 임의 코드 실행을 사용 중단하고 제거하는 것입니다. 이러한 줄은 광범위한 공격 벡터이며, 표준 라이브러리의 exec() 문서에서도 이에 대해 강력히 경고합니다. 이러한 줄을 모듈 내부의 더 제한적인 엔트리 포인트 함수 호출로 대체하면 공격 벡터가 간접적으로 줄어듭니다. 모듈 내부의 함수는 사람과 자동 취약점 검사기 모두가 더 쉽게 감사할 수 있기 때문입니다.
두 번째 개선은 sys.path확장과 엔트리 포인트 명세를 각각 지원하는 정확한 사용 사례에 특화된 두 파일로 분리하는 것입니다. 목적이 서로 섞이지 않고, 효과가 뒤섞일 가능성도 없으며, 파일 형식을 더 읽기 쉽고 처리 규칙도 명확하게 만들 수 있습니다. sys.path확장을 먼저 처리하여 모듈을 임포트할 수 있는 기반을 마련한 다음 엔트리 포인트를 처리합니다. 어떤 파일 형식이 어떤 사용 사례를 지원하는지 명확하게 구분됩니다.
세 번째 개선은 이러한 파일을 처리하는 2단계 접근 방식입니다. 구문 분석 오류를 조기에 보고할 수 있으며 각 파일의 줄에 대한 추가 처리를 종료할 필요도 없습니다. sys.path확장과 엔트리 포인트 호출 모두에서 처리 단계에서 실행 단계로 전환할 때, 어떤 경로 확장과 엔트리 포인트를 허용할지(따라서 안전하다고 간주할지) 명시적으로 제어하는 전역 정책을 설계하고 구현할 기회(in the future)가 생기므로, disabling site.py processing를 완전히 비활성화하는 강력한 수단에 의존하지 않아도 됩니다.
발견된 모든 <name>.pth 파일의 유효한 sys.path확장은 <name>.start 파일의 엔트리 포인트가 호출되기 전에 처리됩니다. 이는 엔트리 포인트 모듈을 임포트하는 데 필요한 모든 sys.path수정 사항이 먼저 적용되도록 하기 위한 것입니다.
엔트리 포인트는 동일한 <name>.start 파일에 여러 번 정의되었는지 또는 둘 이상의 <name>.start 파일에 걸쳐 정의되었는지와 관계없이 중복 제거되지 않습니다. 즉, 엔트리 포인트가 두 번 이상 나타나면 두 번 이상 호출됩니다. sys.path항목의 중복 제거와 달리(중복 항목보다 나중에 sys.path에 디렉터리 경로가 나타나도 아무런 효과가 없음), 사용자는 가능성은 낮더라도 실제로 엔트리 포인트를 여러 번 호출하기를 원할 수 있습니다. 또한 이는 서로 독립적으로 작성된 <name>.start 파일들 사이에서 중복 제거 엔트리 포인트 의미 체계를 정의해야 하는 복잡성도 피합니다.
하위 호환성
이 PEP는 .pth 파일 내부의 import 줄 처리에 대해 3년의 사용 중단 기간을 제안합니다. .pth 파일의 sys.path확장은 변경되지 않은 상태로 유지됩니다.
현재 .pth 파일의 import 줄 임의 코드 실행 기능을 사용하는 모든 패키지에는 항상 간단한 마이그레이션 전략이 있어야 합니다. 해당 패키지는 코드를 패키지 내부의 임포트 가능한 모듈에 있는 호출 가능 객체로 간단히 옮긴 다음, 이 호출 가능 객체의 이름을 <name>.start 파일 내부의 엔트리 포인트 명세에 지정할 수 있습니다.
보안 영향
이 PEP는 인터프리터 시작 중 코드 실행 경로를 더 쉽게 감사할 수 있도록 합니다.
sys.path확장과 코드 실행을 두 개의 별도 파일로 분리하면 사이트 디렉터리의 파일을 나열하는 것만으로도 임의 코드 실행이 정확히 어디에서 발생하는지 알 수 있습니다.- 더 제한적이고 감사 가능한 진입점 실행으로
exec()를 통한 임의 코드 실행을 제거합니다. - Python의 임포트 시스템을 사용하여 엔트리 포인트에 접근하고 실행하므로 표준 감사 후크(PEP 578)를 통해 모니터링할 수 있습니다.
- 2단계 처리 모델은 future 정책 메커니즘이 실행될 항목을 검사하고 제한할 수 있는 자연스러운 후크를 만듭니다.
package.module:callable구문은 임포트 가능한 모듈 내부의 호출 가능 객체로 실행을 제한합니다.
전반적인 시작 전 코드 실행 공격 표면이 이 PEP로 제거되는 것은 아닙니다. 악성 패키지는 여전히 엔트리 포인트를 통해 임의 코드 실행을 유발할 수 있지만, 이 PEP에서 제안하는 메커니즘은 더 구조화되어 있고 감사하기 쉬우며 향후 정책 제어를 적용하기에도 더 적합합니다.
이 내용을 가르치는 방법
작동 방식과 <name>.pth 및 <name>.start 파일의 모범 사례를 설명하도록 site 모듈 문서가 업데이트됩니다. 다음 마이그레이션 지침이 패키지 작성자를 위해 포함됩니다:
- 패키지가 현재
<name>.pth파일을 배포한다면, 이를sys.path확장에 사용하는지 아니면 시작 시 코드 실행에 사용하는지 분석하십시오. 모든sys.path확장 줄은 변경하지 않고 그대로 둘 수 있습니다. import줄의 코드 실행 기능을 사용하고 있다면, 패키지 내부의 가져올 수 있는 모듈에 인자를 받지 않는 호출 가능 객체를 생성하십시오. 일치하는<name>.start파일에서 이를pkg.mod:callable진입점으로 명명하십시오.- 패키지가 이 PEP를 지원하지 않는 이전 Python과 지원하는 최신 Python을 모두 지원해야 한다면,
<name>.pth의import줄을 다음 형식으로 변경하십시오.import pkg.mod; pkg.mod.callable()이렇게 하면 이전 Python은 이
import줄을 실행하고, 최신 Python은 대신<name>.start파일을 사용하여 이를 무시합니다. 두 경우 모두 사실상 동일한 코드가 사용되므로, some 중복이 있기는 하지만 최소한입니다. - 두 Python 버전을 모두 지원하는 기간이 끝나면
<name>.pth파일에서 모든import줄을 제거하십시오.
규범적으로 요구하는 것은 아니지만, 패키지에 <name>.pth 파일과 <name>.start 파일이 모두 포함되어 있고 전자에 후자의 줄과 일치하지 않는 import 줄이 있으면 빌드 도구가 경고를 출력할 수 있습니다.
참조 구현
reference implementation은 이 PEP의 현재 버전을 지원합니다.
거부된 아이디어
.pth파일에 진입점만 추가하고import줄은 그대로 두기- 이는 의도와 위의 설명된 마이그레이션 경로를 혼동하기 때문에 거부됩니다. 관심사 분리 원칙에 따라 패키지가 어떤 사용 사례를 활용하는지 쉽게 이해할 수 있습니다.
<name>.site.toml파일- 이는 이 PEP의 이전 초안에서 제안된 통합된 새 파일 형식입니다. TOML 파일의 구조화된 형식은 지나치다고 여겨졌으며, TOML 파일을 구문 분석하는 오버헤드는 향후 확장성이라는 이점에 비해 가치가 없다고 대체로 판단되었습니다.
- 패키지별 파일 대신 단일 구성 파일
- 사이트 전체 구성 파일 하나를 고려했지만, 독립적으로 설치되는 패키지 간의 조정이 필요하고 도구가 이미 이해하는
<package>.pth규칙을 반영하지 못하므로 거부되었습니다. - 처리 순서를 위한 우선순위 또는 가중치 필드
- 패키지는 독립적으로 설치되므로 우선순위를 결정할 주체가 없습니다. 알파벳순 정렬은 현재의
<name>.pth처리 순서와 일치합니다. 우선순위는 패키지별 메타데이터가 아니라 향후 사이트 전체 정책 구성 파일로 처리할 수 있습니다. - 호출 가능 객체에 인자 전달
- 호출 가능 객체는 단순성을 위해, 그리고 진입점에 전달할 명백히 유용한 인자가 없기 때문에 인자 없이 호출됩니다.
미해결 문제
- 항목 진입점 구문 entry point syntax 섹션에 설명된 대로, 이 PEP는
pkgutil.resolve_name()으로 구현되는 허용 가능한 객체 참조 구문을 좁게 정의하며, 구체적으로pkg.mod:callable구문을 요구할 것을 제안합니다. 이는 직접 가져오기로 인한 부작용, 즉 모듈 범위 수준의 기능을 통한 코드 실행을 장려하고 싶지 않기 때문입니다.이 제한을 허용할 수 있다고 가정하더라도, 이를 어떻게 구현할지는 미해결 문제입니다.
site.py는 이를 직접 강제할 수 있지만, 그러면pkgutil.resolve_name()을 사용하는 목적이 사실상 무색해집니다. PEP 작성자는pkgutil.resolve_name()에 선택적 키워드 전용 인자를 추가하는 방식을 선호하며, 구체적으로strict를 하위 호환성을 위해 기본값False로 설정하는 것입니다.strict=True는 허용 가능한 입력을 사실상W(.W)*:(W(.W)*)로 제한하여, 이전의 콜론이 없는 형식을 거부하고 콜론 뒤의 호출 가능 객체를 필수로 만듭니다. site.addpackage()는 단일.pth파일을 처리하는 문서화되지 않은 함수입니다.site.__all__에 나열되어 있지 않고, Doc/library/site.rst에서도 다루지 않으며, 안정성도 보장되지 않습니다. GitHub 코드 검색 결과, 대략 6개 정도의 서드 파티 프로젝트가 주로site.addpackage(dir, "apps.pth", set())패턴으로 이를 직접 호출하는 것으로 나타났으며 — 이 호출은 모두site.addsitedir(dir)로 대체할 수 있습니다.참조 구현을 작업하는 동안
addpackage()는.pth및.start파일을 처리하는 새로운 내부 파이프라인을 감싸는 얇은 래퍼가 됩니다. 이를 별도의 함수로 유지하면 문서화된 사용 사례가 없음에도 복잡성이 증가합니다. 이 함수는 사용 중단을 권고하고, 사용자에게 문서화된 공개 API인addsitedir()로 마이그레이션하도록 제안해야 합니다.- 현재 PEP는
.pth파일의import줄 처리에 대해 3년의 사용 중단 기간을 권고합니다. 일치하는.start파일이 있으면 사용 중단 기간 동안.pth파일의import줄에 대한 경고가 비활성화되므로, 패키지는 경고 없이 양쪽에 걸쳐 있을 수 있습니다. 그러나 현재 작성된 내용대로라면 사용 중단 기간이 끝날 때 경고가 다시 활성화되므로, 그 시점에는 경고 없이 양쪽에 걸쳐 있을 방법이 없습니다.선호되는 해결책은
.pth파일의import줄에 대한 모든 경고를-v(verbose) 플래그 뒤에 숨기는 것입니다. 이는 5년 전체 기간 동안(3년의 처리 사용 중단 일정은 유지) 적용하거나, 무기한 적용할 수 있습니다. - 향후
-X옵션에서 오류 보고 또는 진입점 실행을 세밀하게 제어할 수 있도록 해야 합니까? - 이 PEP는 이름은 비슷하지만 목적과 동작이 완전히 다른
._pthfiles의 사용을 다루지 않습니다.
변경 이력
19-Apr-2026
<name>.start및<name>.pth파일의 인코딩 요구 사항에 대한 설명을 추가했습니다.- 마이그레이션 지침을 업데이트하십시오.
- 사용 중단 기간 동안 일치하는
<name>.start파일이 없는<name>.pth파일의import줄에 대한 경고는-v(verbose)가 지정된 경우에만 표시됩니다. - 일치하는
<name>.start파일이 있는<name>.pth파일의import줄은 무시된다는 점을 명확히 했습니다. site.addpackage()의 사용 중단과,-v가 지정되지 않는 한.pth파일의import줄 경고를 추가로 2년 동안 억제하는 방안에 관한 open issues를 몇 가지 추가했습니다.
- PEP 제목을 변경했습니다.
- PEP는 더 이상
Packaging주제에 속하지 않습니다. - 이제 PEP는
<name>.pth파일 형식의 발전과 진입점 지정을 위한<name>.start파일의 추가를 제안합니다. 이전 버전의<name>.site.toml파일은 제거되었습니다. .pth파일의import줄에 대해 3년의 사용 중단을 제안합니다.
감사의 말
PEP 작성자는 이 제안의 첫 번째 초안에서 현재 형식으로 절충안에 이르게 된 건설적이고 유익한 대화에 참여해 주신 Paul Moore에게 감사드립니다. 또한 피드백과 격려를 보내 주신 Emma Smith와 Brett Cannon에게도 감사드립니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.