GithubHelp home page GithubHelp logo

pyke's Introduction

Pyke

Pyke is rake-inspired minimalistic [make](http://en.wikipedia.org/wiki/Make_(software) tool for Python.

The core benefit of Pyke over identical systems is the task files organization. There are no mandatory syntax constructions in addition to Python code to get an up-and-running command line interface. No decorators or specific docstrings required.

After pyke module is imported to a script, Pyke automagically translates function definitions to argparse parser configuration. Pyke is actively using function annotations for additional capabilities like command line help and type validation. Also it plays well with default argument values and docstrings.

Usage

Pyke is working identically to the majority of make tools. It allows to execute tasks defined within a specific file named Pykefile. Pykefiles are ordinary Python scripts. Each function from a pykefile is interpreted by Pyke as a separate task available to be executed from the command line.

Here is the basic syntax:

pyke <task> [options]

This command make Pyke to run a specified <task> with some optional arguments ([otions]) from a pykefile located in the current working directory. It is possible to execute pykefile tasks from arbitrary location using -f key, and there is always --help key available to get usage details for base pyke command arguments and pykefile-specific tasks.

Here is an example Pykefile with some basic tasks. Each function demonstrates one of Pyke features, from the most basic use case to advanced one.

"""example pykefile"""

from fnmatch import fnmatch
import math
import hashlib
import os
import re
import shutil
import sys


def ver():
    """show python version"""
    print(sys.version)


def md5(value: 'any text'):
    """calculate md5 hash for a string"""
    m = hashlib.md5()
    m.update(value.encode('utf-8'))
    print(m.hexdigest())


def sum(a: (int, 'first value'), b: (int, 'second value')):
    """sum two values and print the result"""
    print("%d + %d == %d" % (a, b, a + b))


def log(number: (float, 'number'),
        base: (float, 'b', 'logarithm base')=math.e):
    """prints logarithm of a [number] with respect to [base]"""
    print(math.log(number, base))


BLACKLIST = os.pathsep.join([
        '*.pyc',
        '__pycache__',
        '*.egg',
        '*.egg-info',
        'dist',
        'build',
        'sdist',
        'MANIFEST',
    ])

WHITELIST = os.pathsep.join([
        '.git',
    ])


def cleanup(path: (str, 'path'),
            blacklist: (str, 'b', 'files to delete')=BLACKLIST,
            whitelist: (str, 'w', 'files to NOT delete')=WHITELIST,
            dryrun: (bool, 'd', 'dry run')=False):
    """delete temporary files"""
    # check the destination directory path
    if not os.path.isdir(path):
        print('specified path not exists or not a directory')
        return

    # normalize file name pattern lists
    norm = lambda ps: list(filter(None, map(str.strip, ps.split(os.pathsep))))
    whitelist = norm(whitelist)
    blacklist = norm(blacklist)
    dirs2del = []

    if not blacklist:
        print('there is nothing to clean here')
        return

    for dir_path, dir_names, files in os.walk(path):
        if _correspond(dir_path, path, whitelist):
            continue

        for file_name in files:
            file_name = os.path.join(dir_path, file_name)
            if _correspond(file_name, path, blacklist):
                _drop_file(file_name, dryrun)

        if _correspond(dir_path, path, blacklist):
            dirs2del.append(dir_path)

        _drop_dirs(dirs2del, dryrun)


def _match(name, root, pattern):
    """gitignore-style file name pattern matching"""
    match = lambda n, p: fnmatch(n, p) or os.path.basename(n) == p
    return match(name, pattern) or any([match(p, pattern) for p in \
        os.path.relpath(os.path.normpath(name), root).split(os.sep)])


def _correspond(name, root, petterns):
    """check if file [name] matches to one [patterns]"""
    return any([_match(name, root, item) for item in petterns])


def _drop_file(file_name, dryrun):
    """safely delete a file"""
    print("rm %s" % file_name)
    if not dryrun:
        try:
            os.remove(file_name)
        except Exception as ex:
            print("ERROR: %s" % str(ex))


def _drop_dirs(dirs, dryrun):
    """safely delete empty directories in the right order"""
    for dir_path in reversed(sorted(dirs)):
        print("rm -rf %s" % dir_path)
        if not dryrun:
            try:
                shutil.rmtree(dir_path)
            except Exception as ex:
                print("ERROR: %s" % str(ex))

Put this file to current working directory and execute pyke --help command to see how function definitions translates to command line options:

$ pyke --help
usage: pyke [-h] [-n] [-q] [-f PATH] [-v] [--version]
            {cleanup,log,ver,md5,sum} ...

python make tool

positional arguments:
  {cleanup,log,ver,md5,sum}
    cleanup             delete temporary files
    log                 prints logarithm of a [number] with respect to [base]
    ver                 show python version
    md5                 calculate md5 hash for a string
    sum                 sum two values and print the result

optional arguments:
  -h, --help            show this help message and exit
  -n, --dry-run         do a dry run
  -q, --quiet           do not echo commands
  -f PATH, --file PATH  use explicitly specified pykefile
  -v, --verbose         use verbose logging
  --version             show program's version number and exit

It is also possible to get a detailed help for each command:

$ pyke md5 --help
usage: pyke md5 [-h] [-n] [-q] [-f PATH] [-v] [--version] value

python make tool

positional arguments:
  value                 any text

License

pyke's People

Contributors

clbn avatar dreikanter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pyke's Issues

Example tasks

  • Set or increment version, and create a git tag with the same name

Python 2 or Python 3?

Hi, I'm interested in pyke, but am using Python 2. I see that you are using annotations, which are only Python 3, but I'm wondering about your goals. For example, I see a "#!/usr/bin/env python" line in setup.py, which would seem to invoke Python 2. Also, you have utf-8 coding declarations at the top of your files, which aren't needed in Python 3.

Would you be interested in supporting Python 2? The information carried by annotations could optionally be provided by decorators. I'd be interested in helping with the work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.