Skip to content
This repository has been archived by the owner on Oct 7, 2018. It is now read-only.

Conveniently add Angry Michael Phelps anywhere in your project!

License

Notifications You must be signed in to change notification settings

le717/python-package-phelpsface

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

python-package-phelpsface

Conveniently add Angry Michael Phelps anywhere in your project!

Maintainers:

  • Caleb Ely

License:

Brief

This package provides an easy-to-access Angry Michael Phelps image to use anywhere in your project, from internal tool to web app!

More seriously, this project's purpose is to provide a working example for converting a Python package into a wheel for publishing and/or use in other projects.

Usage

  • Be sure Python 3.5+ is installed!
import phelpsface

# Get the direct URL to the image
phelpsface.as_url()

# Return an ASCII art version
phelpsface.as_ascii()

# Also available as an ANSI art version
phelpsface.as_ansi()

# Open the image in a new tab in your default browser
phelpsface.in_browser()

Background

To ease the distribution and installation of a Python library, the maintainer(s) often convert the library into a Python wheel before uploading it to a Python package repository, such as PyPi. However, it is not always clear to learn how to create a wheel. This project aims to ease that boundary by providing a complete Python library, build script, and full explanations from start to finish.

Setting Up

To start, we need some Python code to serve as our library. We will use the ./phelpsface/phelpsface.py module for this purpose. If you open this file, you will see a few methods providing an image of #PhelpsFace in various formats. There is no need to edit this file but you are free to do so if you wish.

Next, we need to install Python and the packages required to build a wheel. Python versions 3.5.0 and higher should work. Start by installing Python if needed, then installing the setuptools and wheel packages by running the following command in a terminal:

$ pip install setuptools wheel
Collecting setuptools
...
Collecting wheel
...
Installing collected packages: setuptools, wheel
Successfully installed setuptools-x.y.z wheel-x.y.z

(The $ indicates a new line in a bash prompt. You do not need to type it, only everything after the $. If you are running Windows, there will not a $.)

setup.py

Now we come to the core of this documentation: ./setup.py. We will use this script to build a wheel. This file is where all the metadata is defined, be it required or recommended. We will only cover the most basic steps needed to build a wheel. If you want to get into advanced usage, refer to the official documentation.

Let us open the file and see what it contains.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from setuptools import setup, find_packages


# Get the package's longer description
# (usually located in the README file)
with open("./README.md", "rt", encoding="utf-8") as f:
    long_description = f.read()

setup(
    name="phelpsface",
    version="1.0.2",
    description="#PhelpsFace",
    url="https://github.com/le717/python-package-phelpsface",
    long_description=long_description,
    long_description_content_type="text/markdown",
    author="Caleb Ely",
    author_email="le717@users.noreply.github.com",
    python_requires=">=3.5",
    package_dir={"": "phelpsface"},
    py_modules=find_packages()
)

That may look like a lot of stuff, but it really is not! Let us break it down into chunks.

from setuptools import setup, find_packages

This allows us to us to use the setup and find_packages functions from the setuptools package we installed earlier. These will perform do the dirty work of creating a wheel for us.

# Get the package's longer description
# (usually located in the README file)
with open("./README.md", "rt", encoding="utf-8") as f:
    long_description = f.read()

Here, we are reading the ./README.md file into a variable called long_description. This makes it easier for us to provide more through documentation for the people who will use our package.

Defining the Metadata

We will detour for just a moment to list and collect the package metadata to give to setup so it can create a wheel.

The following metadata is required to create a wheel:

  • package name
  • package version (in the format major.minor.patch)
  • the file(s) that contains our code

Additionally, the following is a partial list of recommended metadata. We will be including these plus a little bit more.

  • summary
  • longer description
  • project URL (GitHub, GitLab, Azure DevOps, etc.)
  • maintainer name and email

setup()

Now that we have defined what information we needed, let's continue looking at ./setup.py, specifically the setup() function. We will take it one logical chunk at a time.

name="phelpsface",
version="1.0.2",
description="#PhelpsFace",
url="https://github.com/le717/python-package-phelpsface",

In this block, we define our package name to be phelpsface, version it as 1.0.2, write a brief summary (rather oddly called description), and provide the URL to the GitHub repository where the source control lives. So far, straightforward.

long_description=long_description,
long_description_content_type="text/markdown",

Recall earlier that we read the contents of the ./README.md file into a variable called long_description. Here, we use that content as the package's longer description. Because the file is written using Markdown, we need to specify this so it will be handled correctly.

author="Caleb Ely",
author_email="le717@users.noreply.github.com",

Here, we define the package maintainer's name and email address. 👀

python_requires=">=3.5",
package_dir={"": "phelpsface"},
py_modules=find_packages()

This is the most complicated part of the script, and as you will shortly see, it is not even that complicated.

  • python_requires=">=3.5": This package can only be installed on Python installations that are of version 3.5.0 or higher.
  • package_dir={"": "phelpsface"}: Recall that our code is located at ./phelpsface/phelpsface.py. When we build our wheel, we want to allow the user to run import phelpsface to use our code. Without this line, setuptools would not find the code. The dictionary key is the location that we want our code to exist. Using "" as the key means we want it to be at the top-level. The value is the location of our code, in our case, "phelpsface". There is no need to give any path separators.
  • py_modules=find_packages(): setuptools contains a function called find_packages() that generates a list of files that contains your code. By calling this method, we do not have to worry about specifying the individual files and possibly missing one. Alternatively, if we did not want to call this function, we can specify the individual files in a list. For example, because our code lives in phelpsface.py, we would specify phelpsface without the file extension. This line would then read as so: py_modules=["phelpsface"].

setup.cfg

We have one more file to take a look at before we can build our wheel: ./setup.cfg. In a basic form, this file is much simpler than ./setup.py.

[metadata]
# Include the package license in the final wheel file
license_file = LICENSE

As the comment says, all we are doing in this file is telling setuptools to include the package's license file in the final wheel. We do this by providing the license_file key with the appropriate file name, in our case, LICENSE.

Building a Wheel

Now we that we have defined all our metadata, we need to run the following command in a terminal:

$ python ./setup.py bdist_wheel
running bdist_wheel
running build
running build_py
...

When this process finishes, browse the newly created ./dist directory to reveal an even newly created wheel. I am going to list the directory contents in the terminal but viewing the directory in File Explorer works just as well.

$ ls -la ./dist
total 12
drwxr-xr-x 1 Caleb 1049089    0 Sep  7 15:17 ./
drwxr-xr-x 1 Caleb 1049089    0 Sep  7 15:17 ../
-rw-r--r-- 1 Caleb 1049089 8022 Sep  7 15:28 phelpsface-1.0.2-py3-none-any.whl

The only file in the directory, phelpsface-1.0.2-py3-none-any.whl is our generated wheel. If everything in ./setup.py was defined correctly, then you have successfully created a working Python wheel of #PhelpsFace! 👍

Additional Resources

We have only scratched the surface on Python package generation. There is a whole metric ton of additional information available on the Internet. If you would like to learn more, the following are some great resources to consult.