Commit 06780c4f authored by root's avatar root
Browse files

forget the past.

forget the past.
parents
(^|/)\.svn($|/)
(^|/)\.hg($|/)
(^|/)\.hgtags($|/)
^log$
Change log for ail
==================
2005-03-25 -- 0.3.0
* brain can be reloaded
* added ability to use environment variables
* fixed normalize() / quote handling behaviour
* fix various bugs
2004-12-30 -- 0.2.0
* fix problem with quoted text
* fix behaviour with no final command rule for rewritten text (raise an
error)
* support files inclusion
2004-12-03 -- 0.1.3
* use shlex instead of a regexp to split commands
* make tests quiet
2004-10-26 -- 0.1.2
* packaging correction (setup.py)
2004-10-15 -- 0.1.1
* bug corrections
2004-09-22 -- 0.1
* initial release
include ChangeLog
include TODO
include bin/ail
recursive-include test/data *
README for AIL
==============
Distributions
-------------
The source tarball is available at ftp://ftp.logilab.fr/pub/ail.
You may apt-get a debian package by adding ::
deb ftp://ftp.logilab.org/pub/debian unstable/
to your /etc/apt/sources.list files. In bonus
Install
-------
From the source distribution, extract the tarball and run ::
python setup.py install
For debian and rpm packages, use your usual tools according to your Linux
distribution.
Documentation
-------------
Look in the doc/ subdirectory.
Comments, support, bug reports
------------------------------
Use the python-projects@logilab.org mailing list. Since we do not have publicly
available bug tracker yet, bug reports should be emailed there too.
You can subscribe to this mailing list at
http://www.logilab.org/mailinglists/python_projects/mailinglist_register_form
Archives are available at
http://lists.logilab.org/pipermail/python-projects/
Ail's TODO list
------------------
FUNCTIONNALITY :
* detect wrong syntax (infinite loops?)
* include
* réponse préformatée
CMD PROMPT :
* history of commands in prompt - being able to tap 'up' to get
previous command
* reload command in prompt to reload dictionnary
"""the AIL package, macking available everything in the ail.ail module
"""
__revision__ = '$Id: __init__.py,v 1.3 2004-09-24 10:49:30 syt Exp $'
from ail import *
# Copyright (c) 2004 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""
AIL - Artificial Intelligence Language
"""
__revision__ = "$Id: __pkginfo__.py,v 1.16 2005-03-25 14:31:12 adim Exp $"
modname = 'ail'
numversion = (0, 3, 0)
version = '.'.join([str(num) for num in numversion])
pyversions = ('2.3', '2.4')
license = 'GPL'
copyright = '''Copyright (c) 2004 LOGILAB S.A. (Paris, FRANCE).
http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
author = "Logilab"
author_email = "contact@logilab.fr"
short_desc = "regular expression based text processor"
long_desc = """AIL is a pseudo-Natural Language Processor for Artificial \
Intelligence,
inspired by AIML: rewrite text using a set of rules using regular expressions
into commands or answers."""
web = "http://www.logilab.org/projects/%s" % modname
ftp = "ftp://ftp.logilab.org/pub/%s" % modname
mailinglist = "http://lists.logilab.org/mailman/listinfo/ai-projects"
scripts = ['bin/ail']
from os.path import join
include_dirs = [join('test', 'data')]
debian_maintainer = 'Arthur Lutz'
debian_maintainer_email = 'arthur.lutz@logilab.fr'
debian_handler = 'python-library'
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""USAGE: %s [OPTIONS] [ail_file.ail]
start the ail interpreter
OPTIONS:
--help print this help message and exit
:version: $Revision: 1.26 $
:author: Logilab
"""
__revision__ = "$Id: ail.py,v 1.26 2005-03-16 17:35:19 adim Exp $"
__docformat__ = "restructuredtext en"
import getopt
import sys
import re
import shlex
from os.path import basename, dirname, abspath, join
from random import choice
def usage(status=1):
"""display usage and exit
:type status: int
:param status: exit status
"""
print __doc__ % basename(sys.argv[0])
sys.exit(status)
def run(args):
"""command line launcher
:type args: list
:param args: command line arguments, without the script name
"""
long_list = ['help']
try:
optlist, args = getopt.getopt(args, 'h', long_list)
except getopt.error, ex:
print 'Error:', ex
usage(1)
for opt, val in optlist:
if opt in ('-h', '--help'):
usage(0)
brain = Brain(AILBrainHandler())
brain.load(args)
try:
while True :
input = raw_input('>>> ')
try:
answer = brain.think(input)
except NoRewriteError :
answer = '...'
if answer.startswith('assert') :
print "I learned that", answer[6:]
elif answer.startswith('search') :
print "I search for", answer[6:]
else :
print answer
except (KeyboardInterrupt, EOFError) :
# print "I'm dying..."
pass
ENV_VAR = re.compile('\$\{(\w+)\}')
def expand_vars(text, env_vars):
"""replaces variables with their values
:type text: str
:param text: the text to process
:type env_vars: dict
:param env_vars: var/val dictionary
"""
return ENV_VAR.sub(lambda m: env_vars.get(m.group(1), m.group(0)), text)
def read_from_stream(stream, base_dir='', env_context = None):
"""read a AIL formatted file and yield each REWRITE / TERMINAL rules,
formatted as a 3-uple (RULE TYPE, LHS REGEXP, RHS STRING)
"""
return read_from_lines(stream.readlines(), base_dir, env_context)
def read_from_string(string, base_dir='', env_context = None):
return read_from_lines(string.splitlines(), base_dir, env_context)
def read_from_lines(lines, base_dir='', env_context = None):
env_context = env_context or {}
for line in lines:
line = expand_vars(line.strip(), env_context)
if line.startswith('#') or not line :
continue
if '>>' in line :
left, right = line.split('>>')
left, right = left.strip(), right.strip()
if not left.endswith('$'):
left += '$'
yield ('REWRITE', re.compile(left, re.I), right)
elif '::' in line :
left, right = line.split('::')
left, right = left.strip(), right.strip()
right = right.replace('%', '%%')
right = re.sub(r'\\(\d+)', sub_hdlr, right)
if not left.endswith('$'):
left += '$'
yield ('TERMINAL', re.compile(left, re.I), right)
elif line.startswith('include '):
filename = line[8:].strip()
for included_line in read_from_stream(file(join(base_dir, filename)), env_context = env_context):
yield included_line
else:
raise BadAilRule(line)
def sub_hdlr(match):
"""handler function for rgx.sub to transform \n to %(n-1)s"""
return r'%%(%s)s' % (int(match.group(1)) - 1)
class NoRewriteError(Exception):
"""exception used when no more rewrite rules are available"""
class InfiniteCycleError(Exception):
"""exception used when the thinking cycles and doesn't seem to find an end"""
class BadAilRule(Exception):
"""exception used when a malformatted rule is parsed"""
class AILBrainHandler:
"""a default command handler used to interactivly play with ail"""
def command(self, cmdname, *args):
return 'command : %s %s' % (cmdname, str(args))
def random(self, *args):
return choice(args)
def normalize(input):
"""normalize a string by removing new lines an escaping quotes"""
return input.replace("\'", r"\'")
def type_cast(string, encoding=None):
"""type cast a string, handling None, int and float values"""
if string == 'None':
return None
try:
return int(string)
except ValueError:
try:
return float(string)
except:
if encoding is not None:
string = unicode(string, encoding)
return string
class Brain:
"""the ail brain: process text according to loaded rules
"""
def __init__(self, cmds_hdlr, encoding='ISO-8859-1'):
self._patterns = []
self._cmds_hdlr = cmds_hdlr
self.encoding = encoding
self.source_files = []
def load(self, filenames, env_context = None):
"""load rules files"""
for name in filenames:
# print "plugin' brain %s..." % name
self.load_stream(file(name), abspath(dirname(name)), env_context)
self.source_files.append(name)
def reload(self):
"""reloads all rules source files"""
self._patterns = []
filenames = list(self.source_files)
self.source_files = []
self.load(filenames)
def load_stream(self, stream, base_dir='', env_context = None):
"""load rules from stream"""
self._add_patterns(read_from_stream(stream, base_dir, env_context))
def load_string(self, string, base_dir='', env_context = None):
"""load rules from string"""
self._add_patterns(read_from_string(string, base_dir, env_context))
def _add_patterns(self, patterns) :
self._patterns += patterns
def _rewrite(self, input) :
for target, rgx, next in self._patterns:
match = rgx.match(input)
if match is not None:
if target == 'REWRITE':
next = rgx.sub(next, input)
else:
# -> Some of the elements in match.groups() might be None
# if there are optional groups in the regexp => skip them
groups = []
for grp in match.groups():
if grp is None:
groups.append('')
else:
groups.append(normalize(grp))
# print "NEXT = %r, dict = %s" % (next, dict([(str(key), val) for key, val in enumerate(groups)]))
next = next % dict([(str(key), val) for key, val in enumerate(groups)])
return target, next
raise NoRewriteError()
def think(self, input, encoding=None):
"""process the given input, returning the value produced by thinking
(i.e. a direct answer or the result of a command)
"""
if isinstance(input, unicode):
encoding = encoding or self.encoding
input = input.encode(self.encoding)
else:
encoding = None
rule_type, next = self._rewrite(' '.join(input.splitlines()))
cycle_stopper = 0
while rule_type == 'REWRITE' :
cycle_stopper += 1
if cycle_stopper > 1000:
raise InfiniteCycleError
## try:
rule_type, next = self._rewrite(next)
## except NoRewriteError :
## # FIXME (syt+adim): should not catch this exception, imo rewrite without
## # ending command is a bug in the rule file
## return next
## if rule_type == 'TERMINAL':
words = self.split(next)
method = getattr(self._cmds_hdlr, words[0].lower())
return method(*[type_cast(w, encoding) for w in words[1:]])
def split(self, string):
shl = shlex.shlex(string, posix=True)
shl.wordchars += '+-'
shl.escapedquotes += "'"
return list(shl)
def rev_think(self, command, *args):
"""yield rules generating the given command with optional arguments"""
searching = [command] + list(args)
for target, rgx, next in self._patterns:
if target == 'REWRITE':
continue
if self.split(next)[:len(searching)] == searching:
yield rgx.pattern
if __name__ == '__main__' :
run(sys.argv[1:])
I'm pleased to announce the %VERSION% release of %DISTNAME%.
What's new ?
------------
%CHANGELOG%
What is %DISTNAME% ?
------------------------
%LONG_DESC%
Home page
---------
%WEB%
Download
--------
%FTP%
Mailing list
------------
%MAILINGLIST%
%ADDITIONAL_DESCR%
\ No newline at end of file
#!/usr/bin/env python
from ail import run
import sys
run(sys.argv[1:])
usr/share/doc/ail/
usr/share/doc/ail/test
ail (0.3.0-2) unstable; urgency=low
* added package generation for python2.4
-- Adrien Di Mascio <Adrien.DiMascio@logilab.fr> Fri, 25 Mar 2005 15:39:06 +0100
ail (0.3.0-1) unstable; urgency=low
* new upstream release
-- Adrien Di Mascio <Adrien.DiMascio@logilab.fr> Fri, 25 Mar 2005 11:58:46 +0100
ail (0.2.0-1) unstable; urgency=low
* new upstream release
-- Sylvain Thnault <sylvain.thenault@logilab.fr> Thu, 30 Dec 2004 16:12:25 +0100
ail (0.1.3-1) unstable; urgency=low
* New upstream release
* ail-test is now python-ail-test
* ChangeLog correctly installed
-- Sylvain Thenault <sylvain.thenault@logilab.fr> Fri, 3 Dec 2004 10:27:56 +0100
ail (0.1.2-1) unstable; urgency=low
* New ustream release with setup.py corrected
-- Arthur Lutz <arthur.lutz@logilab.fr> Tue, 26 Oct 2004 18:08:49 +0200
ail (0.1.1-1) unstable; urgency=low
* New upstream release
-- Arthur Lutz <arthur.lutz@logilab.fr> Fri, 15 Oct 2004 14:08:26 +0200
ail (0.1-1) unstable; urgency=low
* Initial release
-- Arthur Lutz <arthur.lutz@logilab.fr> Wed, 22 Sep 2004 14:54:45 +0200
Source: ail
Section: python
Priority: optional
Maintainer: Arthur Lutz <arthur.lutz@logilab.fr>
Build-Depends: debhelper (>= 4.0.0), python2.3-dev, python2.4-dev
Standards-Version: 3.6.1
Package: python-ail
Architecture: all
Depends: python (>= 2.3), python (<< 2.4), python2.3-ail (>= ${Source-Version})
Description: regular expression based text processor [dummy package]
AIL is a pseudo-Natural Language Processor for Artificial Intelligence,
inspired by AIML: rewrite text using a set of rules using regular expressions
into commands or answers.
.
This package is an empty dummy package that always depends on a package built
for Debian's default Python version.
.
Homepage: http://www.logilab.org/projects/ail
Package: python-ail-test
Architecture: all
Depends: python-ail (= ${Source-Version}) | python2.3-ail (= ${Source-Version}) | python2.4-ail (= ${Source-Version})
Description: ail's test files
This package contains test files shared by the ail package. It isn't
necessary to install this package unless you want to execute or look at
the tests.
Package: python2.3-ail
Architecture: all
Depends: python2.3
Description: regular expression based text processor [built for python2.3]
AIL is a pseudo-Natural Language Processor for Artificial Intelligence,
inspired by AIML: rewrite text using a set of rules using regular expressions
into commands or answers.
.
This package is built with Python 2.3.
.
Homepage: http://www.logilab.org/projects/ail
Package: python2.4-ail
Architecture: all
Depends: python2.4
Description: regular expression based text processor [built for python2.4]
AIL is a pseudo-Natural Language Processor for Artificial Intelligence,
inspired by AIML: rewrite text using a set of rules using regular expressions
into commands or answers.
.
This package is built with Python 2.4.
.
Homepage: http://www.logilab.org/projects/ail
This package was debianized by Adrien Di Mascio <adrien.dimascio@logilab.fr> Fri, 25 Mar 2005 15:57:23 +0200.
It was downloaded from ftp://ftp.logilab.org/pub/ail
Upstream Author:
Logilab <contact@logilab.fr>
Copyright:
Copyright (c) 2004-2005 LOGILAB S.A. (Paris, FRANCE).
http://www.logilab.fr/ -- mailto:contact@logilab.fr
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307
USA.
On Debian systems, the complete text of the GNU General Public License
may be found in '/usr/share/common-licenses/GPL'.
usr/share/doc/ail/
usr/share/doc/ail/test
usr/lib/python2.3/site-packages
usr/lib/python2.3/site-packages/ail
usr/share/doc/python2.3-ail
#! /bin/sh -e
#
# postinst script for Debian python packages.
# Written 1998 by Gregor Hoffleit <flight@debian.org>.
#
VERSION=2.3
DIRLIST="/usr/lib/python$VERSION/site-packages/ail"
case "$1" in
configure|abort-upgrade|abort-remove|abort-deconfigure)
for i in $DIRLIST ; do
python$VERSION -O /usr/lib/python$VERSION/compileall.py -q $i
python$VERSION /usr/lib/python$VERSION/compileall.py -q $i
done
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
## Alternatives