- 
                Notifications
    
You must be signed in to change notification settings  - Fork 7
 
Packaging a Python project
- 
git init - 
.gitignoreExamples:
- 
pyx-sys and mvdef
- packaged projects with vim swap files and Python build/dist artifacts (
build,dist,.eggsetc.) 
 - packaged projects with vim swap files and Python build/dist artifacts (
 - 
dx
- a packaged project as above, also with 
store/andtmp/data directories 
 - a packaged project as above, also with 
 - emoji-liif with Jupyter notebooks
 
 - 
pyx-sys and mvdef
 
- 
README.mdMore details:
- title e.g. 
# myproject(add a brief description, copy this to the GitHub repo description) - 
## Usage(brief note on what usage will look like if you've not written it yet) - 
## Requirementslist- Python 3and if there are many packages, put them on one line usually- These should be the proper human-readable names (the pip names may differ, they go in requirements.txt)
 - If there are complex conda environment requirements or different options, write a little backticked block
to reproduce it (as here for 
emoji-liif) 
 
 - title e.g. 
 - 
LICENSEDetails/example:
- If you haven't pushed to GitHub yet, copy a LICENSE (the text will be detected)
- E.g. from dx (click 'Raw' to get plain text)
 
 
 - If you haven't pushed to GitHub yet, copy a LICENSE (the text will be detected)
 - 
pyproject.tomlMore details:
- 
Handles the requirements for building binaries/wheels to ship (not required for package users), namely
setuptools,wheel,setuptools_scmfor auto-versioning - 
Copy the one for mvdef
 - 
Versioning is incremented by git tags (see the tags for mvdef for examples). These allow you to do 'releases' (again see mvdef)
- The call to 
git taghas the formatwhere:git tag -a "v$INCREMENTED" -m "$TAG_MESSAGE"
- 
$INCREMENTEDis the next version number (e.g.0.1.2is the next after0.1.1), and it's preceded by "v" - 
$TAG_MESSAGEis a description of the code state at the time it's tagged (similar to a git commit message, an empty or missing git tag message is not allowed). 
 - 
 
 - The call to 
 
 - 
 - 
echo > requirements.txt(if you haven't written any code yet, otherwise list requirements for pip) - 
setup.pyDetails/examples:
- Handles the metadata for pip installation
 - Copy an example like dx
- Change the classifiers for 'intended audience', license, and so on, to match your project
 - 
find_packageswill auto-detect the package insidesrc - If you want command-line entrypoints these can be added (e.g.
mvdef has 4 such 
console_scripts) - The 
version_schemeinterprets thegit tagto auto-version the package accordingly- I use helper functions 
retag_republish_major/minor/micro to automate the simultaneous git tag and PyPi republish steps, see Rebuild Python package for PyPi and republish for code/further details 
 - I use helper functions 
 
 
 
Paths in the following sections are under src/pkgname (replacing 'pkgname' with your package)
- 
shareindicates/src/pkgname/share - 
Handling paths to directories
More details:
- Create modules for each section (e.g. 
share,dataset,model) as well as a top-level__init__.pyand any computation for things to be exported into the main namespace there inutils.py(but do not crowd this directory with anything else!) 
 - Create modules for each section (e.g. 
 - 
Organising different types of data
More details:
- 
Make a deliberate plan about where your data will go within the package, not just the first place that comes to mind.
- Does it really need to be elsewhere on your system? (You can exclude it from the distributed package easily)
 
 - 
Keep data separate from computation on that data
- 
srccontains both but not in the same subdirectories 
 - 
 - 
Keep fixed data files used for computation in
share/data- This will be included in the distributed package via 
setup.pyby settinginclude_package_data=Trueinsetuptools.setup() 
 - This will be included in the distributed package via 
 - 
Keep artifacts [outputs computed from running your package code] in
store/- This will be excluded from the distributed package via 
.gitignoreby the line**/store/* 
 - This will be excluded from the distributed package via 
 - 
Don't put data at the top-level (above
src) outside the package, your code won't be able to interact with it properly (by exposing directory paths from__init__.pyfiles)- 
as done for
dxinshare/data/__init__.pyfrom . import __path__ as _dir_nspath from pathlib import Path as _Path __all__ = ["dir_path"] dir_path = _Path(list(_dir_nspath)[0])
which is then provided to the
share.scraper.parse_topicsmodule:from ..data import dir_path as data_dir
 
 - 
 
 - 
 
Once you've done initial set up for your project locally, go to GitHub and create a repo, copy the description you put in your README to the description
More details
- If it's for a specific organisation (e.g. the engine to drive a website) put it there rather than your personal account
 
Immediately I run these steps (comments are my bashrc aliases)
- There is a gotcha on newer accounts whose default git branch
has been renamed to 
main. Either change your default branch name back to 'master' or modify to suit your default branch name. - GitHub added an extra line to their default suggested workflow, to explicitly declare the branch name, but this is unnecessary (I think just to alert users to the enforced changed defaults) as the line which pushes to the branch includes a branch name and implicitly sets it up for use
 
Code snippet to set up the new package repo
git add --all # gadd
git commit -m "Initial commit" # gcmmtinit
git remote add origin [email protected]:lmmx/pkgname.git # gorigadd pkgname
git push -u origin master # gpushu- 
Create a conda environment for local "editable" pip installation
More details
Having set up a git repo and put a working Python package in it, we can install the package to a conda environment with
pip install -e .(e for--editable)conda create -n pkgname_edit python # gives python=3.9 pip install -e .