Commit 9a6ea408 authored by André Anjos's avatar André Anjos 💬
Browse files

Open-source release

parents
Pipeline #889 passed with stage
*~
*.swp
*.pyc
*.so
bin
eggs
parts
.installed.cfg
.mr.developer.cfg
*.egg-info
develop-eggs
sphinx
doc/api
dist
.nfs*
.gdb_history
build
*.egg
opsnr.stt
.coverage
.DS_Store
src/
html/
py27-linux:
script:
- git clean -ffdx
- export TMPDIR=/var/tmp
- /idiap/project/beat/environments/staging/usr/bin/python bootstrap-buildout.py
- ./bin/buildout
- ./bin/python --version
- unset TMPDIR
- cd src/cpulimit && make && cd -
- cd bin && ln -s ../src/cpulimit/src/cpulimit . && cd -
- export NOSE_WITH_COVERAGE=1
- export NOSE_COVER_PACKAGE=beat.cmdline
- ./bin/nosetests -sv
- ./bin/sphinx-apidoc --separate -d 2 --output=doc/api beat
- ./bin/sphinx-build doc html
tags:
- lidiap2015
py27-macosx:
script:
- git clean -ffdx
- /Users/buildbot/work/environments/beat/py27/bin/python bootstrap-buildout.py
- ./bin/buildout
- ./bin/python --version
- cd src/cpulimit && make && cd -
- cd bin && ln -s ../src/cpulimit/src/cpulimit . && cd -
- export NOSE_WITH_COVERAGE=1
- export NOSE_COVER_PACKAGE=beat.cmdline
- ./bin/nosetests -sv
- ./bin/sphinx-apidoc --separate -d 2 --output=doc/api beat
- ./bin/sphinx-build doc html
tags:
- beat-macosx
.. vim: set fileencoding=utf-8 :
.. Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ ..
.. Contact: beat.support@idiap.ch ..
.. ..
.. This file is part of the beat.web module of the BEAT platform. ..
.. ..
.. Commercial License Usage ..
.. Licensees holding valid commercial BEAT licenses may use this file in ..
.. accordance with the terms contained in a written agreement between you ..
.. and Idiap. For further information contact tto@idiap.ch ..
.. ..
.. Alternatively, this file may be used under the terms of the GNU Affero ..
.. Public License version 3 as published by the Free Software and appearing ..
.. in the file LICENSE.AGPL included in the packaging of this file. ..
.. The BEAT platform 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. ..
.. ..
.. You should have received a copy of the GNU Affero Public License along ..
.. with the BEAT platform. If not, see http://www.gnu.org/licenses/. ..
===========================================================
Authors of the Biometrics Evaluation and Testing Platform
===========================================================
Andre Anjos <andre.anjos@idiap.ch>
Flavio Tarsetti <flavio.tarsetti@idiap.ch>
Laurent El-Shafey <laurent.el-shafey@idiap.ch>
Philip Abbet <philip.abbet@idiap.ch>
Samuel Gaist <samuel.gaist@idiap.ch>
Sebastien Marcel <sebastien.marcel@idiap.ch>
This diff is collapsed.
include LICENSE.AGPL README.rst buildout.cfg bootstrap-buildout.py
recursive-include doc conf.py *.rst *.png *.svg *.ico *.pdf
.. vim: set fileencoding=utf-8 :
.. Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ ..
.. Contact: beat.support@idiap.ch ..
.. ..
.. This file is part of the beat.cmdline module of the BEAT platform. ..
.. ..
.. Commercial License Usage ..
.. Licensees holding valid commercial BEAT licenses may use this file in ..
.. accordance with the terms contained in a written agreement between you ..
.. and Idiap. For further information contact tto@idiap.ch ..
.. ..
.. Alternatively, this file may be used under the terms of the GNU Affero ..
.. Public License version 3 as published by the Free Software and appearing ..
.. in the file LICENSE.AGPL included in the packaging of this file. ..
.. The BEAT platform 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. ..
.. ..
.. You should have received a copy of the GNU Affero Public License along ..
.. with the BEAT platform. If not, see http://www.gnu.org/licenses/. ..
============================================
Biometrics Evaluation and Testing Platform
============================================
This package contains the source code for a python-based command-line client
for the BEAT platform.
Installation
------------
Really easy, with ``zc.buildout``::
$ python bootstrap-buildout.py
$ ./bin/buildout
These 2 commands should download and install all non-installed dependencies and
get you a fully operational test and development environment.
.. note::
The python shell used in the first line of the previous command set
determines the python interpreter that will be used for all scripts developed
inside this package.
If you are on the Idiap filesystem, you may use
``/idiap/project/beat/environments/staging/usr/bin/python`` to bootstrap this
package instead. It contains the same setup deployed at the final BEAT
machinery.
Documentation
-------------
To build the documentation, just do::
$ ./bin/sphinx-apidoc --separate -d 2 --output=doc/api beat beat/cmdline/test beat/cmdline/scripts
$ ./bin/sphinx-build doc sphinx
Testing
-------
After installation, it is possible to run our suite of unit tests. To do so,
use ``nose``::
$ ./bin/nosetests -sv
.. note::
Some of the tests for our command-line toolkit require a running BEAT
platform web-server, with a compatible ``beat.core`` installed (preferably
the same). By default, these tests will be skipped. If you want to run
them, you must setup a development web server and set the environment
variable ``BEAT_CMDLINE_TEST_PLATFORM`` to point to that address. For
example::
$ export BEAT_CMDLINE_TEST_PLATFORM="http://example.com/platform/"
$ ./bin/nosetests -sv
It is **not** adviseable to run tests against a production web server.
If you want to skip slow tests (at least those pulling stuff from our servers)
or executing lengthy operations, just do::
$ ./bin/nosetests -sv -a '!slow'
To measure the test coverage, do the following::
$ ./bin/nosetests -sv --with-coverage --cover-package=beat.cmdline
To produce an HTML test coverage report, at the directory `./htmlcov`, do the
following::
$ ./bin/nosetests -sv --with-coverage --cover-package=beat.cmdline --cover-html --cover-html-dir=htmlcov
Our documentation is also interspersed with test units. You can run them using
sphinx::
$ ./bin/sphinx -b doctest doc sphinx
Development
-----------
Profiling
=========
In order to profile the test code, try the following::
$ ./bin/python -mcProfile -oprof.data ./bin/nosetests -sv ...
This will dump the profiling data at ``prof.data``. You can dump its contents
in different ways using another command::
$ ./bin/python -mpstats prof.data
This will allow you to dump and print the profiling statistics as you may find
fit.
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.cmdline module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform 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. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
#see http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
__import__('pkg_resources').declare_namespace(__name__)
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.cmdline module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform 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. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
#see http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
__import__('pkg_resources').declare_namespace(__name__)
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.cmdline module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform 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. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
"""Usage:
%(prog)s algorithms list [--remote]
%(prog)s algorithms check [<name>]...
%(prog)s algorithms pull [--force] [<name>]...
%(prog)s algorithms push [--force] [--dry-run] [<name>]...
%(prog)s algorithms diff <name>
%(prog)s algorithms status
%(prog)s algorithms create <name>...
%(prog)s algorithms version <name>
%(prog)s algorithms fork <src> <dst>
%(prog)s algorithms rm [--remote] <name>...
%(prog)s algorithms --help
Commands:
list Lists all the algorithms available on the platform
check Checks a local algorithm for validity
pull Downloads the specified algorithms from the server
push Uploads algorithms to the server
diff Shows changes between the local algorithm and the remote version
status Shows (editing) status for all available algorithms
create Creates a new local algorithm
version Creates a new version of an existing algorithm
fork Forks a local algorithm
rm Deletes a local algorithm (unless --remote is specified)
Options:
--force Performs operation regardless of conflicts
--dry-run Doesn't really perform the task, just comments what would do
--remote Only acts on the remote copy of the algorithm
--help Display this screen
Examples:
To list all algorithms available locally:
$ %(prog)s al list
To list all algorithms available at the platform:
$ %(prog)s al list --remote
"""
import logging
logger = logging.getLogger(__name__)
from . import common
from beat.core import algorithm
def pull(webapi, prefix, names, force, indentation, format_cache, lib_cache):
"""Copies algorithms (and required libraries/dataformats) from the server.
Parameters:
webapi (object): An instance of our WebAPI class, prepared to access the
BEAT server of interest
prefix (str): A string representing the root of the path in which the user
objects are stored
names (list): A list of strings, each representing the unique relative path
of the objects to retrieve or a list of usernames from which to retrieve
objects. If the list is empty, then we pull all available objects of a
given type. If no user is set, then pull all public objects of a given
type.
force (bool): If set to ``True``, then overwrites local changes with the
remotely retrieved copies.
indentation (int): The indentation level, useful if this function is called
recursively while downloading different object types. This is normally
set to ``0`` (zero).
format_cache (dict): A dictionary containing all dataformats already
downloaded.
lib_cache (dict): A dictionary containing all libraries already
downloaded.
Returns:
int: Indicating the exit status of the command, to be reported back to the
calling process. This value should be zero if everything works OK,
otherwise, different than zero (POSIX compliance).
"""
from .dataformats import pull as dataformats_pull
from .libraries import pull as libraries_pull
status, names = common.pull(webapi, prefix, 'algorithm', names,
['declaration', 'code', 'description'], force, indentation)
if status != 0: return status
# see what dataformats one needs to pull
indent = indentation * ' '
dataformats = []
libraries = []
for name in names:
obj = algorithm.Algorithm(prefix, name)
dataformats.extend(obj.dataformats.keys())
libraries.extend(obj.libraries.keys())
# downloads any formats to which we depend on
df_status = dataformats_pull(webapi, prefix, dataformats, force,
indentation + 2, format_cache)
lib_status = libraries_pull(webapi, prefix, libraries, force,
indentation + 2, lib_cache)
return status + df_status + lib_status
def process(args):
if args['list']:
if args['--remote']:
with common.make_webapi(args['config']) as webapi:
return common.display_remote_list(webapi, 'algorithm')
else:
return common.display_local_list(args['config'].path, 'algorithm')
elif args['check']:
return common.check(args['config'].path, 'algorithm', args['<name>'])
elif args['pull']:
with common.make_webapi(args['config']) as webapi:
return pull(webapi, args['config'].path, args['<name>'],
args['--force'], 0, {}, {})
elif args['push']:
with common.make_webapi(args['config']) as webapi:
return common.push(webapi, args['config'].path, 'algorithm',
args['<name>'], ['name', 'declaration', 'code', 'description'],
{}, args['--force'], args['--dry-run'], 0)
elif args['diff']:
with common.make_webapi(args['config']) as webapi:
return common.diff(webapi, args['config'].path, 'algorithm',
args['<name>'][0], ['declaration', 'code', 'description'])
elif args['status']:
with common.make_webapi(args['config']) as webapi:
return common.status(webapi, args['config'].path, 'algorithm')[0]
elif args['create']:
return common.create(args['config'].path, 'algorithm', args['<name>'])
elif args['version']:
return common.new_version(args['config'].path, 'algorithm',
args['<name>'][0])
elif args['fork']:
return common.fork(args['config'].path, 'algorithm',
args['<src>'], args['<dst>'])
elif args['rm']:
if args['--remote']:
with common.make_webapi(args['config']) as webapi:
return common.delete_remote(webapi, 'algorithm', args['<name>'])
else:
return common.delete_local(args['config'].path, 'algorithm',
args['<name>'])
# Should not happen
logger.error("unrecognized `algorithms' subcommand")
return 1
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.cmdline module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform 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. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
"""Configuration manipulation and display
Usage:
%(prog)s cache clear
%(prog)s cache info [--start=<index>] [--end=<index>] [--sizes] [<path>]...
%(prog)s cache view [--start=<index>] [--end=<index>] [<path>]...
%(prog)s cache --help
Commands:
clear Deletes all available cache
info Displays information about a particular cache file
view Displays the contents of a particular cache file
Options:
-s, --sizes If set, also print the size in bytes for objects in a file. This
triggers the full file readout
--start=<i> If set, allows the user to print only a few bits of the file
--end=<i> If set, allows the user to print only a few bits of the file
-h, --help Display this screen
Examples:
To clear all available cache:
$ %(prog)s cache clear
To collect information about a particular cache file:
$ %(prog)s cache info 7f/d8/8d/a11178ac27075feaba8131fe878d6e3...
To view a particular cache file:
$ %(prog)s cache view 7f/d8/8d/a11178ac27075feaba8131fe878d6e3...
"""
import os
import fnmatch
import logging
logger = logging.getLogger()
import simplejson
from . import common
from beat.core.data import CachedDataSource, load_data_index
from beat.core.utils import NumpyJSONEncoder
def get_paths(config):
func = lambda z: z.split('.', 1)[0]
retval = []
for dirname, dirs, files in os.walk(config.cache):
files = fnmatch.filter(files, '*.data') #avoid index-only files
if not files: continue
d = dirname.replace(config.cache, '').strip(os.sep)
retval += list(set([os.path.join(d, func(k)) for k in files]))
return retval
def info(config, paths, sizes, index_start, index_end):
if not paths:
paths = get_paths(config)
for path in paths:
logger.info('path: %s', path)
fullpath = os.path.join(config.cache, path + '.data')
f = CachedDataSource()
status = f.setup(fullpath, config.path, index_start, index_end)
if not status:
logger.error("cannot setup data source with `%s' and prefix `%s'",
fullpath, config.path)
return 1
logger.info(' dataformat: %s', f.dataformat.name)
if sizes:
counter = 0
logger.info(' index:')
while f.hasMoreData():
try:
data, start, end = f.next()
except Exception as e:
logger.error("Failed to retrieve the next data: %s", e)
return 1
size = len(data.pack())
counter += size
if start == end:
logger.info(' [%d] - %d bytes', start, size)
else:
logger.info(' [%d:%d] - %d bytes', start, end, size)
logger.info(' total (stripped-down) size: %d bytes', counter)
else:
index = load_data_index(config.cache, path + '.data')
logger.info(' objects : %d', len(index)-1)
return 0
def view(config, paths, index_start, index_end):
if not paths:
paths = get_paths(config)