6. Distutils 예제
*****************

참고:

  이 문서는
  https://setuptools.readthedocs.io/en/latest/setuptools.html 의
  "setuptools" 설명서가 현재 여기에 포함된 모든 관련 정보를 독립적으로
  다루기 전까지만 보존됩니다.

이 장에서는 distutils를 시작하는 데 도움이 되는 여러 가지 기본 예를 제
공합니다. distutils 사용에 대한 추가 정보는 Distutils Cookbook에서 찾
을 수 있습니다.

더 보기:

  Distutils Cookbook
     distutils를 더 잘 제어하는 방법을 보여주는 조리법 모음.


6.1. 순수한 파이썬 배포 (모듈별)
================================

단지 몇 개의 모듈만 배포한다면, 특히 특정 패키지에 속하지 않는 모듈이
면, 설정 스크립트에서 "py_modules" 옵션을 사용하여 개별적으로 지정할
수 있습니다.

가장 간단한 경우, 두 가지 파일을 염두에 두어야 합니다: 설정 스크립트와
배포 할 단일 모듈, 이 예에서는 "foo.py":

   <root>/
           setup.py
           foo.py

(이 섹션의 모든 다이어그램에서 *<root>*는 배포 루트 디렉터리를 가리킵
니다.) 이 상황을 설명하기 위한 최소 설정 스크립트는 다음과 같습니다:

   from distutils.core import setup
   setup(name='foo',
         version='1.0',
         py_modules=['foo'],
         )

배포판의 이름은 "name" 옵션으로 독립적으로 지정되며, 배포판의 유일한
모듈 이름과 같아야 한다는 규칙은 없습니다 (아마도 따라야 할 좋은 규칙
임에도 불구하고). 그러나 배포판 이름은 파일명을 생성하는 데 사용되어서
, 글자, 숫자, 밑줄 및 하이픈만 사용해야 합니다.

"py_modules"는 리스트이므로, 여러 모듈을 지정할 수 있습니다, 예를 들어
"foo"와 "bar" 모듈을 배포한다면, 설정은 다음과 같습니다:

   <root>/
           setup.py
           foo.py
           bar.py

그리고 설정 스크립트는 이렇습니다

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         py_modules=['foo', 'bar'],
         )

모듈 소스 파일을 다른 디렉터리에 넣을 수 있지만, 그렇게 할 모듈이 아주
많다면, 개별적으로 나열하지 않고 패키지로 모듈을 지정하기가 아마도 더
쉽습니다.


6.2. 순수한 파이썬 배포 (패키지별)
==================================

배포할 모듈이 많으면, 특히 여러 패키지에 있다면, 개별 모듈보다는 전체
패키지를 지정하기가 아마도 더 쉽습니다. 모듈이 패키지에 없는 경우에도
작동합니다; 루트 패키지에서 모듈을 처리하도록 Distutils에 지시 할 수
있으며, 다른 패키지와 동일하게 작동합니다 ("__init__.py" 파일이 필요하
지 않다는 것만 다릅니다).

마지막 예제의 설정 스크립트는 다음과 같이 작성할 수도 있습니다

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         packages=[''],
         )

(빈 문자열은 루트 패키지를 나타냅니다.)

이 두 파일이 하위 디렉터리로 이동했지만, 루트 패키지에 남아있다면, 예
를 들어:

   <root>/
           setup.py
           src/      foo.py
                     bar.py

그러면 여전히 루트 패키지를 지정하지만, 루트 패키지의 소스 파일이 어디
에 있는지 Distutils에 알려야 합니다:

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         package_dir={'': 'src'},
         packages=[''],
         )

그러나 더 일반적으로는, 같은 패키지(또는 서브 패키지)에 있는 여러 모듈
을 배포하고자 합니다. 예를 들어, "foo"와 "bar" 모듈이 패키지 "foobar"
에 속하면, 소스 트리를 배치하는 한 가지 방법은 다음과 같습니다:

   <root>/
           setup.py
           foobar/
                    __init__.py
                    foo.py
                    bar.py

이것은 사실 Distutils가 예상하는 기본 배치이며, 설정 스크립트에서 설명
할 작업이 가장 적은 배치입니다:

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         packages=['foobar'],
         )

패키지 이름으로 지정되지 않은 디렉터리에 모듈을 넣으려면,
"package_dir" 옵션을 다시 사용해야 합니다. 예를 들어, "src" 디렉터리에
"foobar" 패키지의 모듈이 있다면:

   <root>/
           setup.py
           src/
                    __init__.py
                    foo.py
                    bar.py

적절한 설정 스크립트는 다음과 같습니다

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         package_dir={'foobar': 'src'},
         packages=['foobar'],
         )

또는, 메인 패키지의 모듈을 배포 루트에 바로 넣을 수 있습니다:

   <root>/
           setup.py
           __init__.py
           foo.py
           bar.py

이 경우 설정 스크립트는 다음과 같습니다

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         package_dir={'foobar': ''},
         packages=['foobar'],
         )

(빈 문자열은 현재 디렉터리를 나타냅니다.)

서브 패키지가 있으면, "packages"에 명시적으로 나열되어야 하지만,
"package_dir"의 모든 항목은 서브 패키지로 자동 확장됩니다. (즉,
Distutils는 "__init__.py" 파일을 찾아서 어떤 디렉터리가 파이썬 패키지
에 해당하는지 파악하려고 시도하면서 소스 트리를 스캔하지 *않습니다*.)
따라서, 기본 배치가 서브 패키지로 뻗어 나가는 경우:

   <root>/
           setup.py
           foobar/
                    __init__.py
                    foo.py
                    bar.py
                    subfoo/
                              __init__.py
                              blah.py

해당 설정 스크립트는 이렇게 됩니다

   from distutils.core import setup
   setup(name='foobar',
         version='1.0',
         packages=['foobar', 'foobar.subfoo'],
         )


6.3. 단일 확장 모듈
===================

확장 모듈은 "ext_modules" 옵션을 사용하여 지정됩니다. "package_dir"은
확장 소스 파일이 있는 위치를 찾는 데 영향을 미치지 않습니다; 순수한 파
이썬 모듈의 소스에만 영향을 미칩니다. 단일 C 소스 파일에 단일 확장 모
듈이 들어 있는, 가장 간단한 경우는 이렇습니다:

   <root>/
           setup.py
           foo.c

"foo" 확장이 루트 패키지에 속하면, 이를 위한 설정 스크립트는 다음과 같
습니다

   from distutils.core import setup
   from distutils.extension import Extension
   setup(name='foobar',
         version='1.0',
         ext_modules=[Extension('foo', ['foo.c'])],
         )

확장이 실제로 패키지에 속하면, 가령 "foopkg"

정확히 같은 소스 트리 배치로, 간단히 확장의 이름을 변경하여 이 확장을
"foopkg" 패키지에 넣을 수 있습니다:

   from distutils.core import setup
   from distutils.extension import Extension
   setup(name='foobar',
         version='1.0',
         ext_modules=[Extension('foopkg.foo', ['foo.c'])],
         )


6.4. 패키지 검사하기
====================

"check" 명령을 사용하면 패키지 메타 데이터가 배포판을 빌드하기 위한 최
소 요구 사항을 충족하는지 확인할 수 있습니다.

실행하려면, "setup.py" 스크립트를 사용하여 호출하십시오. 뭔가 빠진 것
이 있으면, "check"는 경고를 표시합니다.

간단한 스크립트로 예를 들어 봅시다:

   from distutils.core import setup

   setup(name='foobar')

"check" 명령을 실행하면 몇 가지 경고가 표시됩니다:

   $ python setup.py check
   running check
   warning: check: missing required meta-data: version, url
   warning: check: missing meta-data: either (author and author_email) or
            (maintainer and maintainer_email) must be supplied

"long_description" 필드에 reStructuredText 문법을 사용하고 docutils가
설치되었으면 "restructuredtext" 옵션을 사용하여 "check" 명령으로 문법
이 올바른지 확인할 수 있습니다.

예를 들어, "setup.py" 스크립트가 다음과 같이 변경되면:

   from distutils.core import setup

   desc = """\
   My description
   ==============

   This is the description of the ``foobar`` package.
   """

   setup(name='foobar', version='1', author='tarek',
       author_email='tarek@ziade.org',
       url='http://example.com', long_description=desc)

긴 설명이 망가지면, "check"는 "docutils" 구문 분석기를 사용하여 이를
감지할 수 있습니다:

   $ python setup.py check --restructuredtext
   running check
   warning: check: Title underline too short. (line 2)
   warning: check: Could not finish the parsing.


6.5. 메타 데이터 읽기
=====================

"distutils.core.setup()" 함수는 주어진 프로젝트의 "setup.py" 스크립트
를 통해 프로젝트의 메타 데이터 필드를 조회할 수 있는 명령 줄 인터페이
스를 제공합니다:

   $ python setup.py --name
   distribute

이 호출은 "distutils.core.setup()" 함수를 실행하여 "name" 메타 데이터
를 읽습니다. Distutils로 소스나 바이너리 배포판이 만들어질 때, 메타 데
이터 필드는 "PKG-INFO"라는 정적 파일에 기록됩니다. Distutils 기반 프로
젝트가 파이썬에 설치되면, "PKG-INFO" 파일은 배포판의 모듈과 패키지와
함께 "NAME-VERSION-pyX.X.egg-info" 밑에 복사됩니다, 여기서 "NAME"은 프
로젝트 이름, "VERSION"은 메타 데이터에 정의된 버전, "pyX.X"는 "2.7"이
나 "3.2"와 같은 파이썬의 주와 부 버전입니다.

"distutils.dist.DistributionMetadata" 클래스와 "read_pkg_file()" 메서
드를 사용하여, 이 정적 파일을 다시 읽을 수 있습니다:

   >>> from distutils.dist import DistributionMetadata
   >>> metadata = DistributionMetadata()
   >>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info'))
   >>> metadata.name
   'distribute'
   >>> metadata.version
   '0.6.8'
   >>> metadata.description
   'Easily download, build, install, upgrade, and uninstall Python packages'

클래스를 메타 데이터 파일 경로로 인스턴스 화하여 해당 값을 로드 할 수
도 있음에 유의하십시오:

   >>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info'
   >>> DistributionMetadata(pkg_info_path).name
   'distribute'
