Skip to content

Commit

Permalink
#19 add setup.py to distribute PyPI package
Browse files Browse the repository at this point in the history
  • Loading branch information
hjacobs committed Jun 24, 2015
1 parent 2dcefdb commit 350b9c0
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 49 deletions.
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ python:
- "2.7"
install:
- pip install -r requirements.txt
- pip install flake8
script:
- python -m doctest -v pg_view.py
- flake8 pg_view.py
- python setup.py test
- python setup.py flake8
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include *.txt
include *.rst
include *.md
include *.py
110 changes: 64 additions & 46 deletions pg_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
try:
import psycopg2
import psycopg2.extras
psycopg2_available = True
except ImportError:
print('Unable to import psycopg2 module, please, install it (python-psycopg2). Can not continue')
sys.exit(254)
psycopg2_available = False
try:
import curses
curses_available = True
Expand Down Expand Up @@ -101,55 +101,39 @@ def output_method_is_valid(method):
return method in get_valid_output_methods()


# parse command-line options

parser = OptionParser()
parser.add_option('-v', '--verbose', help='verbose mode', action='store_true', dest='verbose')
parser.add_option('-i', '--instance', help='name of the instance to monitor', action='store', dest='instance')
parser.add_option('-t', '--tick', help='tick length (in seconds)', action='store', dest='tick', type='int', default=1)
parser.add_option('-o', '--output-method', help='send output to the following source', action='store',
default=OUTPUT_METHOD.curses, dest='output_method')
parser.add_option('-V', '--use-version', help='version of the instance to monitor (in case it can\'t be autodetected)',
action='store', dest='version', type='float')
parser.add_option('-l', '--log-file', help='direct log output to the file', action='store', default='pg_view.log',
dest='log_file')
parser.add_option('-R', '--reset-output', help='clear screen after each tick', action='store_true', default=False,
dest='clear_screen')
parser.add_option('-c', '--configuration-file', help='configuration file for PostgreSQL connections', action='store',
default='', dest='config_file')
parser.add_option('-p', '--pid', help='always track a given pid (may be used multiple times)',
action='append', type=int, default=[])

options, args = parser.parse_args()
def parse_args():
'''parse command-line options'''

parser = OptionParser()
parser.add_option('-v', '--verbose', help='verbose mode', action='store_true', dest='verbose')
parser.add_option('-i', '--instance', help='name of the instance to monitor', action='store', dest='instance')
parser.add_option('-t', '--tick', help='tick length (in seconds)',
action='store', dest='tick', type='int', default=1)
parser.add_option('-o', '--output-method', help='send output to the following source', action='store',
default=OUTPUT_METHOD.curses, dest='output_method')
parser.add_option('-V', '--use-version',
help='version of the instance to monitor (in case it can\'t be autodetected)',
action='store', dest='version', type='float')
parser.add_option('-l', '--log-file', help='direct log output to the file', action='store', default='pg_view.log',
dest='log_file')
parser.add_option('-R', '--reset-output', help='clear screen after each tick', action='store_true', default=False,
dest='clear_screen')
parser.add_option('-c', '--configuration-file', help='configuration file for PostgreSQL connections',
action='store', default='', dest='config_file')
parser.add_option('-p', '--pid', help='always track a given pid (may be used multiple times)',
action='append', type=int, default=[])

options, args = parser.parse_args()
return options, args

# setup system constants
TICK_LENGTH = 1

TICK_LENGTH = options.tick

output_method = options.output_method

if not output_method_is_valid(output_method):
print('Unsupported output method: {0}'.format(output_method))
print('Valid output methods are: {0}'.format(','.join(get_valid_output_methods())))
sys.exit(1)

if output_method == OUTPUT_METHOD.curses and not curses_available:
print('Curses output is selected, but curses are unavailable, falling back to console output')
output_method == OUTPUT_METHOD.console
output_method = OUTPUT_METHOD.curses

LOG_FILE_NAME = options.log_file
options = None

# truncate the former logs
with open(LOG_FILE_NAME, 'w'):
pass

# set basic logging
logging.basicConfig(format='%(levelname)s: %(asctime)-15s %(message)s', filename=LOG_FILE_NAME)
logger = logging.getLogger(__name__)
logger.setLevel((logging.INFO if options.verbose else logging.ERROR))

log_stderr = logging.StreamHandler()
logger.addHandler(log_stderr)
logger = None


class StatCollector(object):
Expand Down Expand Up @@ -3252,6 +3236,40 @@ def parse_single_line(self, inode):


def main():
global TICK_LENGTH, logger, options

if not psycopg2_available:
print('Unable to import psycopg2 module, please, install it (python-psycopg2). Can not continue')
sys.exit(254)

options, args = parse_args()
TICK_LENGTH = options.tick

output_method = options.output_method

if not output_method_is_valid(output_method):
print('Unsupported output method: {0}'.format(output_method))
print('Valid output methods are: {0}'.format(','.join(get_valid_output_methods())))
sys.exit(1)

if output_method == OUTPUT_METHOD.curses and not curses_available:
print('Curses output is selected, but curses are unavailable, falling back to console output')
output_method == OUTPUT_METHOD.console

LOG_FILE_NAME = options.log_file

# truncate the former logs
with open(LOG_FILE_NAME, 'w'):
pass

# set basic logging
logging.basicConfig(format='%(levelname)s: %(asctime)-15s %(message)s', filename=LOG_FILE_NAME)
logger = logging.getLogger(__name__)
logger.setLevel((logging.INFO if options.verbose else logging.ERROR))

log_stderr = logging.StreamHandler()
logger.addHandler(log_stderr)

user_dbname = options.instance
user_dbver = options.version
clusters = []
Expand Down
127 changes: 127 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import inspect

from setuptools.command.test import test as TestCommand
from setuptools import setup

__location__ = os.path.join(os.getcwd(), os.path.dirname(inspect.getfile(inspect.currentframe())))


def read_module(path):
data = {}
with open(path, 'r') as fd:
exec(fd.read(), data)
return data

meta = read_module('pg_view.py')
NAME = 'pg-view'
MAIN_MODULE = 'pg_view'
VERSION = meta['__version__']
DESCRIPTION = 'PostgreSQL Activity View Utility'
LICENSE = 'Apache License 2.0'
URL = 'https://github.com/zalando/pg_view'
author, email = meta['__author__'].rsplit(None, 1)
AUTHOR = author
EMAIL = email.strip('<>')
KEYWORDS = 'postgres postgresql pg database'

# Add here all kinds of additional classifiers as defined under
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
CLASSIFIERS = [
'Development Status :: 4 - Beta',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
]

CONSOLE_SCRIPTS = ['pg_view = pg_view:main']


class PyTest(TestCommand):

user_options = [('cov=', None, 'Run coverage'), ('cov-xml=', None, 'Generate junit xml report'), ('cov-html=',
None, 'Generate junit html report'), ('junitxml=', None, 'Generate xml of test results')]

def initialize_options(self):
TestCommand.initialize_options(self)
self.cov = None
self.cov_xml = False
self.cov_html = False
self.junitxml = None

def finalize_options(self):
TestCommand.finalize_options(self)
if self.cov is not None:
self.cov = ['--cov', self.cov, '--cov-report', 'term-missing']
if self.cov_xml:
self.cov.extend(['--cov-report', 'xml'])
if self.cov_html:
self.cov.extend(['--cov-report', 'html'])

def run_tests(self):
try:
import pytest
except:
raise RuntimeError('py.test is not installed, run: pip install pytest')
params = {'args': self.test_args}
if self.cov:
params['args'] += self.cov
params['plugins'] = ['cov']
params['args'] += ['--doctest-modules', MAIN_MODULE + '.py', '-s', '-vv']
errno = pytest.main(**params)
sys.exit(errno)


def get_install_requirements(path):
content = open(os.path.join(__location__, path)).read()
return [req for req in content.split('\\n') if req != '']


def read(fname):
return open(os.path.join(__location__, fname)).read()


def setup_package():
# Assemble additional setup commands
cmdclass = {}
cmdclass['test'] = PyTest

install_reqs = get_install_requirements('requirements.txt')

command_options = {}

setup(
name=NAME,
version=VERSION,
url=URL,
description=DESCRIPTION,
author=AUTHOR,
author_email=EMAIL,
license=LICENSE,
keywords=KEYWORDS,
long_description=read('README.md'),
classifiers=CLASSIFIERS,
test_suite='tests',
py_modules=['pg_view'],
packages=[],
install_requires=install_reqs,
setup_requires=['flake8'],
cmdclass=cmdclass,
tests_require=['pytest-cov', 'pytest'],
command_options=command_options,
entry_points={'console_scripts': CONSOLE_SCRIPTS},
)


if __name__ == '__main__':
setup_package()
5 changes: 5 additions & 0 deletions tests/test_dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import pg_view

def test_dummy():
pass

0 comments on commit 350b9c0

Please sign in to comment.