Metadata-Version: 2.1
Name: hellopypa
Version: 0.0.11
Summary: A sample Python package
Home-page: https://github.com/mittelholcz/hellopypa
Author: mittelholcz
License: UNKNOWN
Description: [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/mittelholcz/hellopypa/blob/master/LICENSE)
        [![pypi](https://img.shields.io/badge/pypi-0.0.11-blue.svg)](https://pypi.org/project/hellopypa/)
        
        # Hogyan készítsünk python csomagot
        
        - [1. Bevezetés](#1-bevezetés)
        - [2. Könyvtárszerkezet](#2-könyvtárszerkezet)
        - [3. Környezet](#3-környezet)
        - [4. Az `__init__.py` fájl](#4-az-__init__py-fájl)
        - [5. Tesztelés](#5-tesztelés)
        - [6. A `setup.py` fájl](#6-a-setuppy-fájl)
        - [7. További lehetőségek](#7-további-lehetőségek)
          - [7.1. Verzió](#71-verzió)
          - [7.2. Fájlok hozzáadása](#72-fájlok-hozzáadása)
          - [7.3. Parancssori futtatás](#73-parancssori-futtatás)
        - [TODO](#todo)
        - [Irodalom](#irodalom)
        
        ## 1. Bevezetés
        
        A *modul* (*module*) egy python fájl, ami importálható, névteret alkot és tetszőleges további python objektumokat tartalmazhat.
        
        A *csomag* (*package*) egy olyan könyvtár, ami tartalmaz egy `__init__.py`
        fájlt, továbbá tartalmazhat további alcsomagokat (alkönyvtárakat) és
        modulokat (python fájlokat). A *csomag* is importálható, névteret alkot és
        további python objektumokat tartalmazhat.
        
        *Megjegyzés*: A *modul~fájl* és a *csomag~könyvtár* csak analógia, nem minden
        esetben igaz. Részletek [itt](https://docs.python.org/3/reference/import.html).
        
        A csomagokat a Python csomagkezelőjével, a
        [`pip`](https://pip.pypa.io/en/stable/)-pel lehet telepíteni, frissíteni,
        eltávolítani. A `pip` képes verziókezelő repozitóriumokból is telepíteni, így
        pl. a Github-ról is, de a python csomagok publikálásának szokott módja a
        csomag feltöltése a [pypi.org](https://pypi.org/)-ra (*PyPI*: Python Package
        Index). Ennek mikéntjéről lesz szó az alábbiakban.
        
        A [pypi.org](https://pypi.org/)-ot és a csomagoláshoz szükséges eszközöket a
        *PyPA* (*Python Packaging Authority*) fejleszti és tartja karban. Honlapjukon
        ([pypa.io](https://www.pypa.io/en/latest/)) sok hasznos anyag elérhető
        csomagolás és terjesztés témakörben.
        
        ## 2. Könyvtárszerkezet
        
        ```txt
        hellopypa/
            hellopypa/
                __init__.py
                __main__.py
                example.cfg
                hellopypa.py
                version.py
            test/
                __init__.py
                test_hello.py
            LICENSE
            MANIFEST.in
            README.md
            requirements.txt
            requirements-dev.txt
            setup.py
        ```
        
        Fontosabb könyvtárak és fájlok:
        
        - `hellopypa/`: A csomagunk fő könyvtára. Általában jó, ha ez megegyezik
          magának a repónak a nevével (külső `hellopypa/` könyvtár), de nem szükséges.
        - `test/`: A csomaghoz való tesztek könyvtára. A tesztek nem részei a
          csomagnak, csak a repónak.
        - `LICENSE`: Licenc, a lehetőségeket l. [itt](https://choosealicense.com/) és
          [itt](https://opensource.org/licenses), további tanácsok
          [itt](https://arstechnica.com/gadgets/2020/02/how-to-choose-an-open-source-license/).
        - `MANIFEST.in`: Itt soroljuk fel a csomaghoz tartozó nem python fájlokat (binárisok, konfig fájlok, stb).
        - `README.md`: Readme fájl, röviden leírja, hogy mire jó a csomag, hogyan kell telepíteni és hogyan lehet futtatni. A *markdown* formátumról bővebben [itt](https://guides.github.com/features/mastering-markdown/), a tartalmáról [itt](https://dbader.org/blog/write-a-great-readme-for-your-github-project) lehet olvasni.
        - `requirements*.txt`: Ezekben vannak felsorolva azok a python csomagok, amelyeket használunk (függőségek). A `requirements.txt` tartalmazza magának a csomagnak a függőségeit, a `requirements-dev.txt` pedig a fejlesztéshez szükséges függőségeket (tesztelés, linter, stb).
        - `setup.py`: Ez a fájl tartalmazza csomagoláshoz kellő metaadatokat.
        
        ## 3. Környezet
        
        Hozzunk létre a csomagnak külön virtuális környezetet és aktiváljuk
        (részletek [itt](https://docs.python.org/3/library/venv.html) és
        [itt](https://docs.python.org/3/tutorial/venv.html)):
        
        ```txt
        python3 -m venv .venv
        source .venv/bin/activate
        ```
        
        Telepítsük a csomaghoz (`requirements.txt`) valamint a csomagoláshoz és
        fejlesztéshez szükséges függőségeket (`requirements-dev.txt`):
        
        ```sh
        pip install -r requirements-dev.txt
        ```
        
        *Megjegyzés*: A `requirements-dev.txt` importálja sima `requirements.txt`-t is.
        A `requirements.txt` fájlok leírását l.
        [itt](https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format)
        és [itt](https://pip.pypa.io/en/stable/user_guide/#requirements-files).
        
        A csomagoláshoz az alábbi csomagok szükségesek:
        
        - `setuptools`: Ez a `setup.py` függősége.
        - `twine`: Ezzel lehet a [pypi.org](https://pypi.org/)-ra feltölteni az
          elkészült csomagot.
        - `wheel`: Ez kell a 2012-ben bevezetett *wheel* csomagformátumhoz (l. [PEP
          427](https://www.python.org/dev/peps/pep-0427/)).
        
        ## 4. Az `__init__.py` fájl
        
        Az `__init__.py` lehet üres is, de ekkor is léteznie kell. Ha nem üres, akkor
        a csomag importálásánál a tartalma végrehajtódik. Szokás a metaadatok és az
        API meghatározására használni.
        
        *Metaadatok*: Kisebb projekteknél itt lehet felsorolni a csomag szerzőit,
        verzióját, licencét, megadni email-címet, karbantartót, hálát kifejezni a
        hozzájárulóknak, stb. Részletek [itt](https://stackoverflow.com/a/1523456). A
        verziót érdemes külön fájlban tartani, l. alább a *Verzió* fejezetet.
        
        *API*: Alapesetben ha használni szeretnénk egy importált csomag egy függvényét,
        akkor azt így tudjuk hívni:
        
        ```txt
        csomag[.alcsomag].fájl.függvény()
        ```
        
        Ebből a `csomag`-ot és a `függvény`-t nem lehet elhagyni, de az `alcsomag` és
        a `fájl` általában felesleges. A felhasználónak csak azt kellene
        megjegyeznie, hogy melyik függvény melyik csomagban van, azt nem, hogy melyik
        csomag melyik fájljában van. Ráadásul a csomag írói is szeretik a kódot
        rugalmasan átszervezni a háttérben, pl. egy nagyra nőtt fájl egy részét
        új fájlba írni anélkül, hogy eltörnék az *API*-t.
        
        Mivel az `__init__.py`-ban található kód importáláskor végrehajtódik,
        ezért érdemes itt importálni a publikusnak szánt függvényeket, osztályokat, ezzel a csomag importálásakor ezek az objektumok is közvetlenül használhatók lesznek. Példa:
        
        ```py
        # mypackage/__init__.py
        from file1 import function1, function2
        from file2 import function3
        ```
        
        Ezután a használat egyszerű:
        
        ```py
        import mypackage
        mypackage.function1()
        ```
        
        *Megjegyzés*: Ha az `__init__.py`-ban csillaggal importálunk (`from file
        import *`), akkor az alulvonással kezdődő objektumok nem kerülnek
        importálásra (a teljes elérési útjukon keresztül továbbra is elérhetőek
        lesznek, részletek
        [itt](https://dbader.org/blog/meaning-of-underscores-in-python)).
        
        ## 5. Tesztelés
        
        Mielőtt csomagolnánk, teszteljük le az alkalmazásunkat. A teszteléshez
        használhatjuk a hagyományos
        [*unittest*](https://docs.python.org/3/library/unittest.html)-et, vagy az
        újabban elterjedt [*pytest*](https://docs.pytest.org/en/latest/)-et. A
        `test/` könyvtárban vannak a tesztfájlok, ezeket *pytest* estén a következő
        paranccsal futtathatjuk:
        
        ```sh
        pytest --verbose test/
        ```
        
        *Megjegyzés*: a `test/` könyvtár maga is csomag, kell benne lennie
        `__init__.py` fájlnak.
        
        ## 6. A `setup.py` fájl
        
        Magát a csomagolást (a terjeszthető és telepíthető formátum létrehozását) a
        [*setuptools*](https://setuptools.readthedocs.io/en/latest/) nevű python
        csomag végzi. A `setup.py` fájl tartalmazza a *setuptools* számára szükséges
        adatokat. Az adatokat lehet közvetlenül a `setup.py`-ba is beírni, de néha
        hasznosabb máshol tárolni az adatot és a `setup.py`-ban csak importálni, vagy
        más módon beolvasni.
        
        Egy viszonylag minimalista példa:
        
        ```py
        import setuptools
        
        with open('README.md', 'r') as fh:
            long_description = fh.read()
        
        setuptools.setup(
            name='csomagnév',
            version='0.0.1',
            author='szerző',
            description='Minimalista példa csomag',
            long_description=long_description,
            long_description_content_type='text/markdown',
            url='https://github.com/szerző/csomagnév',
            packages=setuptools.find_packages(exclude=['test']),
            classifiers=[
                'Programming Language :: Python :: 3',
                'License :: OSI Approved :: MIT License',
                'Operating System :: POSIX :: Linux',
            ],
            python_requires='>=3.6',
        )
        ```
        
        A *setuptools.setup* fontosabb mezői:
        
        - `name`: A csomag neve (kötelező).
        - `version`: A csomag verziója (kötelező). A pypi.org-ra nem lehet kétszer
          ugyanazt a verziószámú csomagot feltölteni, akkor sem, ha amúgy különböznek.
        - `author`: A csomag szerzője.
        - `description`: Rövid leírás.
        - `long_description`: Hosszú leírás, jellemzően magát a README.md-t szokták
          megadni. A PyPI ezt fogja a csomag oldalán megjeleníteni. Ha *markdown* fájlt
          adunk meg, akkor meg kell adnunk a formátumot is
          ([*.rst*](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html)
          az alapértelmezett).
        - `url`: A projekt honlapja.
        - `packages`: Itt adható meg, hol keresse a python fájlokat. Érdemes a
          *setuptools* `find_packages()` függvényére bízni a dolgot. Az `exclude=[dir1,
          dir2, ...]` paraméternek megadott könyvtárakban nem fog keresni.
        - `classifiers`: A PyPI számára megadható címkék listája [itt](https://pypi.org/classifiers/).
        - `python_requires`: Megadható a minimum python verzió.
        
        Futtassuk a `setup.py` fájlt:
        
        ```sh
        python3 setup.py sdist bdist_wheel
        ```
        
        A repónkban három új könyvtár fog létrejönni: egy `build/`, egy `dist/` és
        egy `csomagnév.egg-info/` (érdemes ezeket a `.gitignore` fájlba felvenni,
        vagy a GitHub python-hoz írt `.gitignore`
        [fájlját](https://github.com/github/gitignore/blob/master/Python.gitignore)
        használni). Ezek közül a `dist/` ami fontos, ebben található ugyanis a
        csomagunk terjeszthető és telepíthető változata.
        
        A csomag közvetlenül telepíthető a `pip install .` paranccal, vagy
        regisztrációt követően feltölthető a pypi.org oldalra a következő paranccsal:
        
        ```sh
        python3 -m twine upload dist/*
        ```
        
        Ezután bármelyik gépen telepíthető a csomag a `pip install csomagnév`
        paranccsal.
        
        A pypi.org oldalnak van egy teszt változata is, ha csak kísérletezni
        szeretnénk, javasolt ezt használni. A fenti parancsok ekkor így módosulnak:
        
        ```sh
        twine upload --repository-url https://test.pypi.org/legacy/ dist/*
        pip install --index-url https://test.pypi.org/simple/ hellopypa
        ```
        
        ## 7. További lehetőségek
        
        További tanácsok és lehetőségek a terjeszthető csomag testreszabására.
        
        ### 7.1. Verzió
        
        A csomag verzióját érdemes egy helyen tárolni csak és máshol csak innen beolvasni. A lehetőségeket l. [itt](https://packaging.python.org/guides/single-sourcing-package-version/). Az alábbi megoldás lényege, hogy a csomagon belül egy külön fájlt használunk erre (`hellopypa/version.py`). Ezt a fájlt importáljuk a `setup.py`-ban és a `hellopypa/__init__.py`-ban is. Ezzel elkerülhetők a `hellopypa/__init__.py` közvetlen importálásának problémái (l. az előbbi cikk 6. pontjához írt figyelmeztetést), de telepítés nélkül is hozzáférhető lesz a verzió, mintha az `__init__.py`-ban lenne közvetlenül.
        
        ```py
        # hellopypa/version.py
        __version__ = '0.0.3'
        ```
        
        ```py
        # hellopypa/__init__.py
        # ...
        from hellopypa.version import __version__
        # ...
        ```
        
        ```py
        # setup.py
        # ...
        from hellopypa.version import __version__
        # ...
        setuptools.setup(
            # ...
            version=__version__,
            # ...
        )
        ```
        
        ### 7.2. Fájlok hozzáadása
        
        A *setuptools* csak a python fájlokat veszi figyelembe. Ha más fájlokat is a
        csomaghoz szeretnénk adni (konfigurációs fájlokat, binárisokat, adatot),
        akkor két dolgot kell csinálnunk.
        
        1. Létre kell hoznunk egy *MANIFEST.in* fájlt, amiben felsoroljuk, hogy miket
        szeretnénk még a csomaghoz adni. Részletek
        [itt](https://packaging.python.org/guides/using-manifest-in/). Példa: adjuk a
        projekthez a *.cfg* kiterjesztésű fájlokat.
        
            ```txt
            # MANIFEST.in
            include hellopypa/*.cfg
            ```
        
        2. A *setup.py*-ba is bele kell írni, hogy további fájlok is lesznek.
        
            ```py
            # setup.py
            # ...
            setuptools.setup(
                # ...
                include_package_data=True,
                # ...
            )
            ```
        
        ### 7.3. Parancssori futtatás
        
        Ha csomagunkat a `pip install hellopypa` után nem csak importálva, de
        parancssori alkalmazásként is szeretnénk használni, akkor két dolgot
        tehetünk.
        
        1. Egy python csomag futtatható az `-m` kapcsolóval (pl. `# python -m
        hellopypa`). Ehhez az kell, hogy a csomagban legyen egy `__main__.py` fájl, a
        python ezt fogja keresni és ha létezik, akkor futtatni. Részletek (nem mintha
        nagyon lennének) [itt](https://docs.python.org/3/library/__main__.html).
        2. Egy python csomag futtatható rendes, telepített parancsként is (pl.
        `# hellopypa`). Ekkor a *setup.py*-ban meg kell adni egy úgynevezett belépési
        pontot, konkrétan egy függvényt, amit meg fog hívni a python. Részletek
        [itt](https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points).
        Példa:
        
            ```py
            # setup.py
            # ...
            setuptools.setup(
                # ...
                entry_points={
                    "console_scripts": [
                        "hellopypa=hellopypa.__main__:main",
                    ]
                },
                # ...
            )
            ```
        
        ## 8. Make
        
        *Átmeneti megoldás, amíg nincs rendes automatizálás.*
        
        `make clean`: A build-elés során keletkezett könyvtárak törlése (`buld/`,
        `dist/`, `*.egg-info/`).
        
        `make test`: Tesztek futtatása.
        
        `make build`: Build-elés.
        
        `make release_major`: *Major* verziószám váltás, új release a GitHub-on és a
        PyPI-n.
        
        `make release_minor`: *Minor* verziószám váltás, új release a GitHub-on és a
        PyPI-n.
        
        `make release_patch`: *Patch* verziószám váltás, új release a GitHub-on és a
        PyPI-n.
        
        
        ## TODO
        
        - [x] Tartalom
        - [x] Bevezetés: modul, csomag, pypi
        - [x] Könyvtárszerkezet
        - [x] Környezet
        - [x] Tesztelés
        - [ ] Dokumentáció
        - [x] A `setup.py` fájl
        - [x] A `MANIFEST.in` fájl
        - [x] `__main__.py`, CLI
        - [x] `__init__.py`, API
        - [x] Verziózás
        - [x] Csomagolás
        - [x] Közzététel
        - [ ] Automatizálás
        - [x] Telepítés
          - [x] lokálisan
          - [x] pypi
        - [x] make
        - [ ] függőség buildelése a setup.py használatával???
        - [ ] függőség letöltése telepítéskor???
        
        ## Irodalom
        
        - PyPA gyorstalpalója: <https://packaging.python.org/tutorials/packaging-projects/>
        - PyPA útmutatói egyes témákhoz: <https://packaging.python.org/guides/>
        - *Real Python* tutorial: <https://realpython.com/pypi-publish-python-package/>
        - *setuptools* dokumentáció: <https://setuptools.readthedocs.io/en/latest/>
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.6
Description-Content-Type: text/markdown
