나도 할 수 있다 오픈소스

효준 강
효준 강Spoqa의 Programmer at 스포카
나도 할 수 있다 오픈소스!
setup.py에서 PyPI까지
강효준 Kang Hyojun
오픈 소스 시작하기
            .
          , 뭔가 복잡하고 어려워보인다.
 PR    리뷰하기 어렵다.
오픈 소스 시작하기
                .
setup.py     ,        .
        .. 
achimnol/pycon apac2018 packaging workshop
          ,                .
pyleftpad를 PyPI에 배포해봅시다
https://github.com/admire93/pyleftpad
$ pip install pyleftpad
$ leftpad -l 5 -f 0 foo
00foo
pyleftpad를 PyPI에 배포해봅시다
예제 함수
def leftpad( 
  source: Union[str, int], 
  padded: int, 
  fill_value: Union[str, int] 
)  > str:
...
return result
디렉토리 구조
/pyleftpad
/leftpad
__init__.py
func.py
cli.py
setup.py
setup.cfg
README.md
CHANGES.md
CONTRIBUTING.md
LICENSE
/docs
/tests
.travis.yml
setup.py 작성
from setuptools import setup
setup(
name='pyleftpad',
version='0.1.0',
...
)
천리 길도 setup.py 부터
setuptools
     /     
 
distutils
→ setuptools
Distribute
Distutils2
scikit build
setuptools.setup
         
             
   
   
     
setuptools.setup
Metadata
name ,  version ,  url ,  download_url ,  project_urls ,  author ,  author_email ,
maintainer ,  maintainer_email ,  classifiers ,  license ,  description ,
long_description ,  long_description_content_type ,  keywords ,  platforms ,  provides ,
requires ,  obsoletes
Options
zip_safe ,  setup_requires ,  install_requires ,  extras_require ,  python_requires ,
entry_points ,  use_2to3 ,  use_2to3_fixers ,  use2to3_exclude_fixers ,
convert_2to3_doctests ,  scripts ,  eager_resources ,  dependency_links ,
tests_require ,  include_package_data ,  packages ,  package_dir ,  package_data ,
exclude_package_data ,  namespace_packages ,  py_modules ,
setuptools.setup 인자
  :  name
    :  author ,
author_email
setup(
name='pyleftpad',
author='Kang Hyojun',
author_email='foo' '@' 'gmail.com'
)
setuptools.setup 인자
  :  name
    :  author ,
author_email
  :  description ,
long_description
        .
long_description_content_type
setup(
description='Python leftpad',
long_description=readme(),
long_description_content_type=
'text/markdown',
)
setuptools.setup 인자
  :  name
    :  author ,
author_email
  :  description ,
long_description
        .
long_description_content_type
def readme()  > str:
with open('./README.md') as f:
return f.read()
setuptools.setup 인자
  :  name
    :  author ,
author_email
  :  description ,
long_description
        .
long_description_content_type
:  license :
https://choosealicense.com/
지금까지 채워넣은 setuptools.setup
setup(
name='pyleftpad',
author='Kang Hyojun',
author_email='iam.kanghyojun' '@' 'gmail.com',
description='Python leftpad',
long_description=readme(),
license='GPL',
)
setuptools.setup 인자
    version
       
    :  url
setup(
version='0.1.0',
url='https://github.com/admire93/'
'pyleftpad',
)
PEP 396 — Module Version Numbers
          ,  __version__       .
[N ]N(.N)*[{a|b|rc}N][.postN][.devN] — PEP 440
  .
VCS             .
setup.py   version       __version__     ,     
.
PEP 396 — Module Version Numbers
from leftpad import __version__
setup(
...
version=__version__,
...
)
PEP 396 — Module Version Numbers
__init__.py      
 
  ,       
  constant    
  setup.py    
:mod:`leftpad`   Leftpad 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
from .constant import DEFAULT_PADDING
__version__ = '0.1.0'
PEP 396 — Module Version Numbers
ast     __init__.py     __version__        
import ast
def get_version():
filename = 'leftpad/__init__.py'
with open(filename, 'r') as f:
tree = ast.parse(f.read(), filename)
for node in tree.body:
if (isinstance(node, ast.Assign) and
node.targets[0].id == '__version__'):
return ast.literal_eval(node.value)
else:
raise ValueError('could not find __version__')
setuptools.setup 인자 (2)
  :  packages  vs  py_modules
py_modules :       
,            .
packages :       
    .
setuptools.find_packages()  
      .
setup(
...
# or use find_packages()
py_modules='leftpad.py',
classifiers=[
...
],
...
)
setuptools.setup 인자 (2)
  :  classifiers
         
 
   PyPI   
 
https://pypi.org/pypi?
%3Aaction=list_classifiers
setuptools.setup 인자 (2)
  :  classifiers
         
 
   PyPI   
 
https://pypi.org/pypi?
%3Aaction=list_classifiers
 PyPI       
setuptools.setup 인자 (3)
  :  entry_ponits
Dynamic Discovery
     
CLI        
setup(
...,
entry_points={
'console_scripts': [
'leftpad=leftpad:cli'
],
},
...
)
setuptools.setup 인자 (3)
  :  entry_ponits
Dynamic Discovery
     
CLI        
$ pip install leftpad
$ leftpad 'foo'
  'foo'
$ pip install httpie
$ http get http://example.com
...
setuptools.setup 인자 (4)
패키지 의존성 관리
install_requires :     
tests_require :       
extras_require :     
install_requires=[
'flask >= 1.0.2, < 1.1',
'click == 6.7',
],
tests_require=['pytest', 'flake'],
extras_require={
'crypto': ['crypto'],
...
},
패키지 의존성 관리
tests_require     extras_require
       
     
$ pip install pyleftpad[crypto]
setup.cfg 사용하기
  setup.cfg          
setuptools 30.3.0 (2016  12  8   )     
setup.cfg 사용하기
예제
[metadata]
name = my_package
version = attr: src.VERSION
...
classifiers =
Framework :: Django
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
[options]
packages = find:
scripts =
bin/first.py
bin/second.py
install_requires =
requests
importlib; python_version == 2.6
setup.cfg 사용하기
pyleftpad에 적용
[metadata]
name = pyleftpad
version = attr: leftpad.__version__
description = Python leftpad
long_description = file: README.md
long_description_content_type = text/markdown
keywords = leftpad, pyleftpad
license = GPLv3
classifiers =
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Topic :: Utilities
Development Status :: 3 - Alpha
Environment :: Console
[options]
packages = find:
[options.entry_points]
console_scripts = leftpad = leftpad.cli:main
PyPI
Python Package Index
https://pypi.org/
PyPI에 가입하기
https://pypi.org/account/register/
PyPI          
 
           
      .
PyPI 설정
~/.pypirc    
repository   password      
password    CLI    
  .
[distutils]
index-servers = pypi
[pypi]
repository:
   https://upload.pypi.org/legacy/
username: <username>
password: <password>
PyPI에 업로드하기
$ python setup.py sdist upload
       
     
Wheel로 업로드하기
$ pip install wheel
$ python setup.py sdist bdist_wheel upload
Wheel?
Wheels are the new standard of Python
distribution and are intended to
replace eggs. Support is offered in pip
>= 1.4 and setuptools >= 0.8.
egg       
   C         
 
       
CI              
    setup.py    
Wheel VS Egg
https://packaging.python.org/discussions/wheel vs egg/
Wheel  PEP 0427  Egg   .
Egg           , Wheel    
Wheel  .pyc     
Wheel로 업로드 완료
 .whl   PyPI       
.
{ }-{ }-{ }.whl
twine
       
       PyPI  HTTPS    
keyring         
twine
         
  twine      
$ python setup.py sdist bdist_wheel
$ twine upload dist/*
twine
         
  twine      
   
$ twine upload 
--repository-url https://test.pypi.org/legacy/ 
dist/*
협업하기
    ,    (   )    
               
        ,         
기여 가이드하기
GitHub      
     
Setting guidelines for repository
contributors
CONTRIBUTING      
 
  : atom    
CoC        
  .
기여 가이드하기
GitHub      
     
Setting guidelines for repository
contributors
CONTRIBUTING      
 
  : atom    
CoC        
    .
풀 리퀘스트 템플릿 이용하기
pull_request_template.md      PR     
PR          
## PR을 올리기전에..
, .
 [ ] diff [     ][google test review] .
 [ ] / .
## tl;dr
...
[google test review]: https://testing.googleblog.com/2017/06/code health too many comments on your.h
풀 리퀘스트 템플릿 이용하기
           
           
   
변경 기록 항상 적기
               
     
    (Changelog)  CI            
변경 기록 항상 적기
if git show --format=%B --quiet $TRAVIS_PULL_REQUEST_SHA 
| grep '[changelog skip]' > /dev/null; then
echo Skip changelog checker...
elif [[ $TRAVIS_TAG != ]]; then
! grep -i to be released CHANGES.md
else
[[ $TRAVIS_COMMIT_RANGE = ]] || 
[[ $(git diff  name only  $TRAVIS_COMMIT_RANGE  | grep CHANGES.md) != ]]
fi
귀찮은 일 미루기
CI  (CircleCI   TravisCI)  git     
GitHub 
deploy:
  provider: releases
  api_key: GITHUB OAUTH TOKEN
  file: FILE TO UPLOAD
  skip_cleanup: true
  on:
    tags: true
귀찮은 일 미루기
CI  (CircleCI   TravisCI)  git     
PyPI      
deploy:
  provider: pypi
  user: ...
  password: ...
  on:
    tags: true
README에 배지 달기
CI, readthedocs, code coverage             
            .
   
README에 배지 달기
GitHub으로 코드 관리하기
     
close
closes
closed
fix
fixes
fixed
resolve
resolves
resolved
매장과 고객을 세련되게 연결하다
recruit@spoqa.com
감사합니다
질문있으신가요?
iam.kanghyojun(at)gmail.com
kanghyojun.org
1 of 54

More Related Content

What's hot(20)

Isolated development in pythonIsolated development in python
Isolated development in python
Andrés J. Díaz851 views
Debugging concurrency programs in goDebugging concurrency programs in go
Debugging concurrency programs in go
Andrii Soldatenko320 views
Pytest - testing tips and useful pluginsPytest - testing tips and useful plugins
Pytest - testing tips and useful plugins
Andreu Vallbona Plazas159 views
Bdd: Tdd and beyond the infiniteBdd: Tdd and beyond the infinite
Bdd: Tdd and beyond the infinite
Giordano Scalzo32.8K views
PyPy's approach to construct domain-specific language runtimePyPy's approach to construct domain-specific language runtime
PyPy's approach to construct domain-specific language runtime
National Cheng Kung University4.6K views
python-message-0.1.0python-message-0.1.0
python-message-0.1.0
勇浩 赖739 views
Python Programming Essentials - M18 - Modules and PackagesPython Programming Essentials - M18 - Modules and Packages
Python Programming Essentials - M18 - Modules and Packages
P3 InfoTech Solutions Pvt. Ltd.1.9K views
FunctionsFunctions
Functions
Marieswaran Ramasamy2.3K views
Annotation processingAnnotation processing
Annotation processing
Florent Champigny268 views
Intro To Spring PythonIntro To Spring Python
Intro To Spring Python
gturnquist5.8K views
Python Programming Essentials - M25 - os and sys modulesPython Programming Essentials - M25 - os and sys modules
Python Programming Essentials - M25 - os and sys modules
P3 InfoTech Solutions Pvt. Ltd.2.9K views
Puppi. Puppet strings to the shellPuppi. Puppet strings to the shell
Puppi. Puppet strings to the shell
Alessandro Franceschi5.8K views

Recently uploaded(20)

나도 할 수 있다 오픈소스