DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 967,611 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
abdelino17
abdelino17

Posted on

Building a package as per the PyPA Guidelines

Python is definitely the language you MUST to learn in 2022.
Originally developed by Guido van Rossum in 1991, it is used in a wide variety of industries, ranging from education to medicine.

There are various tools and techniques for creating and distributing packages.

The Python Packaging Authority (PyPA) proposes guidelines for building and sharing python packages.

In this article, we will write a small python package implementing the LRU Cache.

For recall, The Least Recently Used (LRU) is a caching strategy consisting to evict elements from the cache to make room for new elements when the cache is full. In short, the least recently items are discarded first.

Here is the code of the LRU Cache:

from collections import OrderedDict

class LRUCache(OrderedDict):

    def __init__(self, capacity: int):
        self.capacity = capacity

    def put(self, key: str, value: str) -> None:
        if key in self:
            self.move_to_end(key)
        self[key] = value
        if len(self) > self.capacity:
            self.popitem(last=False)

    def get(self, key: str) -> int | str:
        if key not in self:
            return -1
        self.move_to_end(key)
        return self[key]

    def show_entries(self) -> None:
        print(self)
Enter fullscreen mode Exit fullscreen mode

PyPA recommends using a sample project for building reusable packages and is available at: https://github.com/pypa/sampleproject.
PyPA Sample Project

The most important files to remember are:

  • setup.py: script for building and installing the package. It contains a global setup() function.
  • setup.cfg: this is a configuration file that can be used by setup.py to define default.
  • setup(): you can pass many arguments to this function such as Name, Version, Description, URL, Author, License.
  • data: place to add data files if needed.
  • tests: placeholder to add unit tests for the modules.
  • src/<package>: top-level package containing all the modules and packages inside it.

Let’s clone the repo and modify it:

$ git clone https://github.com/pypa/sampleproject.git lru-cache
Enter fullscreen mode Exit fullscreen mode

We updated setup.py with arguments as per our package project. Here is a snippet of our file:

setup(
    name="lrucache",
    version="0.1.0",
    description="LRU Cache for illustration purpose",
    long_description=long_description,
    long_description_content_type="text/markdown",  
    url="https://github.com/abdelino17/lru-cache",
    author="Abdel FARE",  
    author_email="fare.abdel@gmail.com", 
    keywords="cache, lru, setuptools, development", 
    package_dir={"": "src"}, 
    packages=find_packages(where="src"),  
    python_requires=">=3.7, <4",
    project_urls={
        "Bug Reports": "https://github.com/abdelino17/lru-cache/issues",
        "Source": "https://github.com/abdelino17/lru-cache"
    }
)
Enter fullscreen mode Exit fullscreen mode

With this setup.py file, we are ready to share our lru-cache package locally as well as to the world.

Before building, here is the structure of our package:
Structure of our package

For simplicity purpose, Let's add this to the __init__.py file:

from .lrucache import LRUCache
Enter fullscreen mode Exit fullscreen mode

Here is the content of our test file:

import unittest

from lrucache import LRUCache

CACHE_CAPACITY = 3

class TestLRUCache(unittest.TestCase):

    def setUp(self) -> None:
        super().setUp()
        self.lruCache = LRUCache(CACHE_CAPACITY)

    def test_cache(self):
        self.lruCache.put("1", "1")
        self.lruCache.put("2", "2")
        self.lruCache.put("3", "3")

        self.assertEqual(self.lruCache.get("1"), "1")
        self.assertEqual(self.lruCache.get("3"), "3")

        self.lruCache.put("4", "4")
        self.assertEqual(self.lruCache.get("2"), -1)

        self.lruCache.put("5", "5")
        self.assertEqual(self.lruCache.get("1"), -1)


if __name__ == '__main__':
    unittest.main()
Enter fullscreen mode Exit fullscreen mode

Installing from the local source

Let’s execute the following command to install the package from the local source:

$ pip install <path_to_package>
Enter fullscreen mode Exit fullscreen mode

The following is the console output of the command:
Output of installation

Our package was installed successfully and we can now use it from the command line:
Usage of our module

Publishing a package to Test PyPI.

As a next step, we will add our sample package to the PyPI Test repository.

Before executing any command for publishing our package, we will need to create an account and get an API token on Test PyPI.

You could find all the information for creating and adding the token on the Test PyPI website.

To push the package, we will also need the Twine utility. You can install it with pip:

$ pip install twine
Enter fullscreen mode Exit fullscreen mode

Now, we are ready to upload our package, For that, we will execute the following steps:

1.Create a distribution using the following command:

$ python setup.py sdist
Enter fullscreen mode Exit fullscreen mode

2.Upload the distribution file to Test PyPI.

$ twine upload --repository testpypi dist/lrucache-0.1.0.tar.gz
Enter fullscreen mode Exit fullscreen mode

This command will push the package file to our Test PyPI repository.
Pushing to Test PyPI

There we go! Our package is now available for the community.
Package Page

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.