diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..297bacc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +Gora Khargosh +Joshaven Potter + +Based on the work of Joshaven Potter at: +https://github.com/joshaven/string_score/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0cedbca --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (C) 2010 by Gora Khargosh +Copyright (C) 2009 Joshaven Potter + +MIT License +----------- +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..34729ad --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,5 @@ +include README +include AUTHORS +include LICENSE +include quicksilver.py + diff --git a/README b/README new file mode 100644 index 0000000..375179c --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +quickslipper +============ + +Quicksilver style pattern matching. diff --git a/buildout.cfg b/buildout.cfg new file mode 100644 index 0000000..2ee9049 --- /dev/null +++ b/buildout.cfg @@ -0,0 +1,39 @@ +[buildout] +develop = . +#offline = true +parts = + python + ipython + tests + docs +eggs = + quickslipper + +[python] +recipe = zc.recipe.egg +interpreter = python +eggs = + ${buildout:eggs} + +[ipython] +recipe = zc.recipe.egg +eggs = + ipython + ${tests:eggs} + ${buildout:eggs} +scripts = ipython + +[tests] +recipe = zc.recipe.egg +interpreter = python-tests +eggs = + nose + coverage + pythoscope + ${buildout:eggs} + +[docs] +recipe = zc.recipe.egg +eggs = + sphinx + sphinx-pypi-upload diff --git a/nose.cfg b/nose.cfg new file mode 100644 index 0000000..e488103 --- /dev/null +++ b/nose.cfg @@ -0,0 +1,6 @@ +[nosetests] +verbosity=3 +with-doctest=1 +#with-color=1 +#with-noseexclude=1 +#exclude-dir-file=tests/nose-exclude.txt diff --git a/quickslipper.py b/quickslipper.py new file mode 100644 index 0000000..2117eb3 --- /dev/null +++ b/quickslipper.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# quickslipper.py: Quicksilver-like string scoring algorithm. +# Copyright (C) 2010 Gora Khargosh +# Copyright (C) 2009 Joshaven Potter +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + diff --git a/scripts/autobuild.sh b/scripts/autobuild.sh new file mode 100755 index 0000000..ebc8ea8 --- /dev/null +++ b/scripts/autobuild.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# autobuild.sh: Monitors the source directory for documentation file changes +# and builds it continuously in the background. +# +# Public domain. +# + +bin/python scripts/nosy.py . diff --git a/scripts/bootstrap.py b/scripts/bootstrap.py new file mode 100755 index 0000000..8c13e94 --- /dev/null +++ b/scripts/bootstrap.py @@ -0,0 +1,129 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. + +$Id$ +""" + +import os, shutil, sys, tempfile, urllib2 +from optparse import OptionParser + +tmpeggs = tempfile.mkdtemp() + +is_jython = sys.platform.startswith('java') + +# parsing arguments +parser = OptionParser( + 'This is a custom version of the zc.buildout %prog script. It is ' + 'intended to meet a temporary need if you encounter problems with ' + 'the zc.buildout 1.5 release.') +parser.add_option("-v", "--version", dest="version", default='1.4.4', + help='Use a specific zc.buildout version. *This ' + 'bootstrap script defaults to ' + '1.4.4, unlike usual buildout bootstrap scripts.*') +parser.add_option("-d", "--distribute", + action="store_true", dest="distribute", default=True, + help="Use Distribute rather than Setuptools.") +parser.add_option("-s", "--setuptools", + action="store_true", dest="setuptools", default=False, + help="Use Setuptools rather than Distribute.") +parser.add_option("-c", None, action="store", dest="config_file", + help=("Specify the path to the buildout configuration " + "file to be used.")) + +options, args = parser.parse_args() + +# if -c was provided, we push it back into args for buildout' main function +if options.config_file is not None: + args += ['-c', options.config_file] + +if options.version is not None: + VERSION = '==%s' % options.version +else: + VERSION = '' + +USE_DISTRIBUTE = not options.setuptools +args = args + ['bootstrap'] + +to_reload = False +try: + import pkg_resources + if not hasattr(pkg_resources, '_distribute'): + to_reload = True + raise ImportError +except ImportError: + ez = {} + if USE_DISTRIBUTE: + exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' + ).read() in ez + ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) + else: + exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' + ).read() in ez + ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) + + if to_reload: + reload(pkg_resources) + else: + import pkg_resources + +if sys.platform == 'win32': + def quote(c): + if ' ' in c: + return '"%s"' % c # work around spawn lamosity on windows + else: + return c +else: + def quote (c): + return c + +ws = pkg_resources.working_set + +if USE_DISTRIBUTE: + requirement = 'distribute' +else: + requirement = 'setuptools' + +env = dict(os.environ, + PYTHONPATH= + ws.find(pkg_resources.Requirement.parse(requirement)).location + ) + +cmd = [quote(sys.executable), + '-c', + quote('from setuptools.command.easy_install import main; main()'), + '-mqNxd', + quote(tmpeggs)] + +if 'bootstrap-testing-find-links' in os.environ: + cmd.extend(['-f', os.environ['bootstrap-testing-find-links']]) + +cmd.append('zc.buildout' + VERSION) + +if is_jython: + import subprocess + exitcode = subprocess.Popen(cmd, env=env).wait() +else: # Windows prefers this, apparently; otherwise we would prefer subprocess + exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) +assert exitcode == 0 + +ws.add_entry(tmpeggs) +ws.require('zc.buildout' + VERSION) +import zc.buildout.buildout +zc.buildout.buildout.main(args) +shutil.rmtree(tmpeggs) diff --git a/scripts/nosy.py b/scripts/nosy.py new file mode 100755 index 0000000..84614ef --- /dev/null +++ b/scripts/nosy.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# nosy: continuous integration for watchdog +# +# Copyright (C) 2010 Gora Khargosh +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" +:module: nosy +:synopsis: Rewrite of Jeff Winkler's nosy script tailored to testing watchdog +:platform: OS-independent +""" + +import os.path +import sys +import stat +import time +import subprocess +from fnmatch import fnmatch + + +def match_patterns(pathname, patterns): + """Returns ``True`` if the pathname matches any of the given patterns.""" + for pattern in patterns: + if fnmatch(pathname, pattern): + return True + return False + + +def filter_paths(pathnames, patterns=None, ignore_patterns=None): + """Filters from a set of paths based on acceptable patterns and + ignorable patterns.""" + result = [] + if patterns is None: + patterns = ['*'] + if ignore_patterns is None: + ignore_patterns = [] + for pathname in pathnames: + if match_patterns(pathname, patterns) and not match_patterns(pathname, ignore_patterns): + result.append(pathname) + return result + + +def absolute_walker(pathname, recursive): + if recursive: + walk = os.walk + else: + def walk(_path): + try: + return next(os.walk(_path)) + except NameError: + return os.walk(_path).next() + for root, directories, filenames in walk(pathname): + yield root + for directory in directories: + yield os.path.abspath(os.path.join(root, directory)) + for filename in filenames: + yield os.path.abspath(os.path.join(root, filename)) + + +def glob_recursive(pathname, patterns=None, ignore_patterns=None): + full_paths = [] + for root, _, filenames in os.walk(pathname): + for filename in filenames: + full_path = os.path.abspath(os.path.join(root, filename)) + full_paths.append(full_path) + filepaths = filter_paths(full_paths, patterns, ignore_patterns) + return filepaths + + +def check_sum(pathname='.', patterns=None, ignore_patterns=None): + checksum = 0 + for f in glob_recursive(pathname, patterns, ignore_patterns): + stats = os.stat(f) + checksum += stats[stat.ST_SIZE] + stats[stat.ST_MTIME] + return checksum + + +if __name__ == "__main__": + if len(sys.argv) > 1: + path = sys.argv[1] + else: + path = '.' + + if len(sys.argv) > 2: + command = sys.argv[2] + else: + commands = [ + # Build documentation automatically as well as the source code + # changes. + "make SPHINXBUILD=../bin/sphinx-build -C docs html", + + # The reports coverage generates all by itself are more + # user-friendly than the ones which `nosetests --with-coverage` + # generates. Therefore, we call `coverage` explicitly to + # generate reports, and to keep the reports in synchronization + # with the source code, we erase all coverage information + # before regenerating reports or running `nosetests`. + "bin/coverage erase", + "bin/python-tests tests/run_tests.py", + "bin/coverage html", + ] + command = '; '.join(commands) + + + previous_checksum = 0 + while True: + calculated_checksum = check_sum(path, patterns=['*.py', '*.rst', '*.rst.inc']) + if calculated_checksum != previous_checksum: + previous_checksum = calculated_checksum + subprocess.Popen(command, shell=True) + time.sleep(2) + + + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f0b2c18 --- /dev/null +++ b/setup.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# setup.py: Setup information. +# Copyright (C) 2010 Gora Khargosh +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import imp +from setuptools import setup + +def read_file(filename): + """ + Reads the contents of a given file relative to the directory + containing this file and returns it. + + :param filename: + The file to open and read contents from. + """ + return open(os.path.join(os.path.dirname(__file__), filename)).read() + +setup(name='quickslipper', + version='0.0.1', + description='Quicksilver-like pattern matching', + long_description=read_file('README'), + author="Gora Khargosh", + author_email="gora.khargosh@gmail.com", + license="MIT License", + url="http://github.com/gorakhargosh/quickslipper", + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries', + 'Topic :: Utilities', + ] + )