Skip to main content

Generate unoccupied name.

Project description

Unoccupied

Find an unoccupied name from basename & occupied names.

If you tired to write a bunch of code to deal unnamed note 02, pic-03.jpg, archive.part4.zip naming problem. It's for you.

Features

  • Based on basename: find an unoccupied name as close as user wanted, not randomly.
  • Isolated: pure function API, no related outer environment like filesystem or DB.
  • Stable: consider edge situations and already be tested.
  • Flexible: library user can choice / overwrite naming algorithm easily.

Usage

Basic Usage

Use basename and occupied container (an iterable) to find a unoccupied name:

from unoccupied import unoccupied

basename = 'foo'



unoccupied(basename, [])  # 'foo' not be occupied
# >>> 'foo'

unoccupied(basename, ['foo'])  # 'foo' already be occupied
# >>> 'foo-1'

unoccupied(basename, ['foo', 'foo-1'])  # 'foo' & 'foo-1' already be occupied
# >>> 'foo-2'

Name Finder

Name finder offer an algorithm to find (or generate) an unoccupied name.

Let's try to change the default name finder:

from unoccupied import unoccupied
from unoccupied import NumberNameFinder  # A built-in name finder generator

# test data
basename = 'foo'
occupied = ['foo', 'bar', 'foo-1']



unoccupied(basename, occupied)  # use defualt name finder
# >>> 'foo-2'

name_finder = NumberNameFinder(template='{basename}-{num:02}')  # <- look here
unoccupied(basename, occupied, name_finder)
# >>> 'foo-01'

Another case: Assume we need to find an unoccupied filename, but, we don't want the base filename foo.txt become foo.txt-1. The foo-1.txt is much suitable name. Try the built-in FileNameFinder().

from unoccupied import unoccupied
from unoccupied import FileNameFinder  # here

# test data
basename = 'pic.jpg'
occupied = ['pic.jpg', 'pic-1.jpg', 'foo']  # may use os.listdir() in real case



unoccupied(basename, occupied, FileNameFinder())  # <- look here
# >>> 'pic-2.jpg'

name_finder = FileNameFinder(template='{base}.{num:02}', start=0)
unoccupied(basename, occupied, name_finder)
# >>> 'pic.00.jpg'

Build a Name Finder

A name_finder is just a callable accept 2 arguments: (basename, norm_occupied), so feel free to build your own. e.g.:

import string
from unoccupied import unoccupied

def alphabet_name_finder(basename, norm_occupied):
    for char in string.ascii_lowercase:
        testing_name = '{}-{}'.format(basename, char)
        if testing_name not in norm_occupied:
            return testing_name

unoccupied('foo', ['foo'], alphabet_name_finder)
# >>> 'foo-a'

Or, using BaseNameFinder class to build a name_finder:

import string
from unoccupied import unoccupied
from unoccupied import BaseNameFinder


class AlphabetNameFinder(BaseNameFinder):
    """Basic alphabet name finder."""
    def ids_generator(self):
        return string.ascii_lowercase

alphabet_name_finder = AlphabetNameFinder()

unoccupied('foo', ['foo'], alphabet_name_finder)
# >>> 'foo-a'


class AlphabetNameFinder2(BaseNameFinder):
    """Configurable alphabet name finder."""
    def __init__(self, template):       # here is a configurable option.
        self.template = template

    def ids_generator(self):
        return string.ascii_lowercase

    def formatter(self, basename, id):  # change formatting algorithm
        return self.template.format(basename=basename, id=id)

alphabet_name_finder2 = AlphabetNameFinder2(template='{basename}.{id}')

unoccupied('foo', ['foo'], alphabet_name_finder2)
# >>> 'foo.a'

As you see. BaseNameFinder packed some tedious work like for-loop & infinite loop checking. And good for offer some configurable options for further usage.

Reference

function unoccupied(basename, occupied, name_finder=NumberNameFinder(), skipbase=False)

Find a unoccupied name.

  • basename: (str) the wanted basename.
  • occupied: (str of iterable) the names already be occupied.

name_finder is a callable with 2 arguments (basename, norm_occupied). This function only be called when basename cannot use directly, and it should return None or string. Return None mean it can't find any unoccupied name and cause unoccupied() raise UnoccupiedNameNotFound exception.

Hint: occupied will be convert to frozenset data type (we call it norm_occupied) and inject to name_finder. If and only if you try to build a name_finder by yourself, you may need to know that.

skipbase is a boolean value. If True, basename will not return directly, no matter the basename already in occupied or not. So user can generate a consistent name series like pic-01, pic-02 and without pic.

class BaseNameFinder()

This is the base class of built-in NameFinder class. It has 2 method which can (but not necessary) be overwrited:

method ids_generator(self) -> Iterable

This method will create a series of id and push into self.formatter().

method formatter(self, basename, id) -> str

This method can assemble basename and id then return a string by any algorithm.

class NumberNameFinder(template='{basename}-{num}', start=1)

Generate a name_finder to find an unoccupied name with basename and an increasing number.

The template argument is a python str.format() template. This template can include 2 keyword params. {basename} represent the original basename. {num} represent an increasing number.

start argument can define what {num} starts from.

class FileNameFinder(template='{base}-{num}', start=1)

Generate a name_finder to find an unoccupied name with processed filename and an increasing number.

The template argument is a python str.format() template. This template can include 2 keyword params. {base} represent the filename without extension. {num} represent an increasing number. Hint: the filename extension will be appended automatically.

start argument can define what {num} starts from.

Test

./setup.py test  # or pytest

Install

pip install unoccupied

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unoccupied-0.2.2.tar.gz (6.9 kB view details)

Uploaded Source

Built Distribution

unoccupied-0.2.2-py3-none-any.whl (5.6 kB view details)

Uploaded Python 3

File details

Details for the file unoccupied-0.2.2.tar.gz.

File metadata

  • Download URL: unoccupied-0.2.2.tar.gz
  • Upload date:
  • Size: 6.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for unoccupied-0.2.2.tar.gz
Algorithm Hash digest
SHA256 a1e949106c844bb0c250f6e43c7c037383f02ecb0a5d78e95ef4f4b32d081483
MD5 a3393e9eb42db782482c29c6f6c596eb
BLAKE2b-256 95318f82e086bb72fb8cf124fcf4eea7d8fa01d5fbb4e74dbbb5e2fcc9cc2a18

See more details on using hashes here.

File details

Details for the file unoccupied-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for unoccupied-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f0c667e33447ca87e2e99237e051681207da767643b032e10efdb442baef71d5
MD5 90ce8f80ab8210ddea4558b99e92d2e4
BLAKE2b-256 c4f9456dc9af4858fed2b9b642278e737ccf09850dd3d31d83212037e62e1f72

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page