From ba81ec1af62a75517dbbf558b1e894f90f274815 Mon Sep 17 00:00:00 2001
From: Tiago Freitas Pereira <tiagofrepereira@gmail.com>
Date: Mon, 21 Nov 2016 10:12:29 +0100
Subject: [PATCH] [refactoring2016] Doing the refactoring

---
 .gitlab-ci.yml              | 249 ++++++++++++++++++++++++++++++++++++
 README.rst                  |  69 +++-------
 bob/db/cuhk_cufsf/create.py |   7 +-
 bob/db/cuhk_cufsf/models.py |   4 +-
 bob/db/cuhk_cufsf/query.py  |  29 +++--
 bob/db/cuhk_cufsf/utils.py  |   4 +-
 doc/extra-intersphinx.txt   |   1 +
 doc/guide.rst               |   2 +-
 doc/nitpick-exceptions.txt  |   2 +
 requirements.txt            |   6 +
 setup.py                    |  12 +-
 11 files changed, 310 insertions(+), 75 deletions(-)
 create mode 100644 .gitlab-ci.yml
 create mode 100644 doc/extra-intersphinx.txt
 create mode 100644 doc/nitpick-exceptions.txt
 create mode 100644 requirements.txt

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..fa11e07
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,249 @@
+# This build file heavily uses template features from YAML so it is generic
+# enough for any Bob project. Don't modify it unless you know what you're
+# doing.
+
+
+# Definition of our build pipeline
+stages:
+  - build
+  - test
+  - docs
+  - wheels
+  - deploy
+
+
+# ---------
+# Templates
+# ---------
+
+# Template for the build stage
+# Needs to run on all supported architectures, platforms and python versions
+.build_template: &build_job
+  stage: build
+  before_script:
+    - git clean -ffdx
+    - mkdir _ci
+    - curl --silent "https://gitlab.idiap.ch/bob/bob.admin/raw/master/gitlab/install.sh" > _ci/install.sh
+    - chmod 755 _ci/install.sh
+    - ./_ci/install.sh _ci #updates
+    - ./_ci/before_build.sh
+  script:
+    - ./_ci/build.sh
+  after_script:
+    - ./_ci/after_build.sh
+  artifacts:
+    expire_in: 1 week
+    paths:
+      - _ci/
+      - dist/
+      - sphinx/
+
+
+# Template for the test stage - re-installs from uploaded wheels
+# Needs to run on all supported architectures, platforms and python versions
+.test_template: &test_job
+  stage: test
+  before_script:
+    - ./_ci/install.sh _ci #updates
+    - ./_ci/before_test.sh
+  script:
+    - ./_ci/test.sh
+  after_script:
+    - ./_ci/after_test.sh
+
+
+# Template for the wheel uploading stage
+# Needs to run against one supported architecture, platform and python version
+.wheels_template: &wheels_job
+  stage: wheels
+  environment: intranet
+  only:
+    - master
+    - /^v\d+\.\d+\.\d+([abc]\d*)?$/  # PEP-440 compliant version (tags)
+  before_script:
+    - ./_ci/install.sh _ci #updates
+    - ./_ci/before_wheels.sh
+  script:
+    - ./_ci/wheels.sh
+  after_script:
+    - ./_ci/after_wheels.sh
+
+
+# Template for (latest) documentation upload stage
+# Only one real job needs to do this
+.docs_template: &docs_job
+  stage: docs
+  environment: intranet
+  only:
+    - master
+  before_script:
+    - ./_ci/install.sh _ci #updates
+    - ./_ci/before_docs.sh
+  script:
+    - ./_ci/docs.sh
+  after_script:
+    - ./_ci/after_docs.sh
+
+
+# Template for the deployment stage - re-installs from uploaded wheels
+# Needs to run on a single architecture only
+# Will deploy your package to PyPI and other required services
+# Only runs for tags
+.deploy_template: &deploy_job
+  stage: deploy
+  environment: internet
+  only:
+    - /^v\d+\.\d+\.\d+([abc]\d*)?$/  # PEP-440 compliant version (tags)
+  except:
+    - branches
+  before_script:
+    - ./_ci/install.sh _ci #updates
+    - ./_ci/before_deploy.sh
+  script:
+    - ./_ci/deploy.sh
+  after_script:
+    - ./_ci/after_deploy.sh
+
+
+# -------------
+# Build Targets
+# -------------
+
+# Linux + Python 2.7: Builds, tests, uploads wheel and deploys (if needed)
+build_linux_27:
+  <<: *build_job
+  variables: &linux_27_build_variables
+    PYTHON_VERSION: "2.7"
+    WHEEL_TAG: "py27"
+  tags:
+    - conda-linux
+
+test_linux_27:
+  <<: *test_job
+  variables: *linux_27_build_variables
+  dependencies:
+    - build_linux_27
+  tags:
+    - conda-linux
+
+wheels_linux_27:
+  <<: *wheels_job
+  variables: *linux_27_build_variables
+  dependencies:
+    - build_linux_27
+  tags:
+    - conda-linux
+
+deploy_linux_27:
+  <<: *deploy_job
+  variables: *linux_27_build_variables
+  dependencies:
+    - build_linux_27
+  tags:
+    - conda-linux
+
+
+# Linux + Python 3.4: Builds and tests
+build_linux_34:
+  <<: *build_job
+  variables: &linux_34_build_variables
+    PYTHON_VERSION: "3.4"
+    WHEEL_TAG: "py3"
+  tags:
+    - conda-linux
+
+test_linux_34:
+  <<: *test_job
+  variables: *linux_34_build_variables
+  dependencies:
+    - build_linux_34
+  tags:
+    - conda-linux
+
+
+# Linux + Python 3.5: Builds, tests and uploads wheel
+build_linux_35:
+  <<: *build_job
+  variables: &linux_35_build_variables
+    PYTHON_VERSION: "3.5"
+    WHEEL_TAG: "py3"
+  tags:
+    - conda-linux
+
+test_linux_35:
+  <<: *test_job
+  variables: *linux_35_build_variables
+  dependencies:
+    - build_linux_35
+  tags:
+    - conda-linux
+
+wheels_linux_35:
+  <<: *wheels_job
+  variables: *linux_35_build_variables
+  dependencies:
+    - build_linux_35
+  tags:
+    - conda-linux
+
+docs_linux_35:
+  <<: *docs_job
+  variables: *linux_35_build_variables
+  dependencies:
+    - build_linux_35
+  tags:
+    - conda-linux
+
+
+# Mac OSX + Python 2.7: Builds and tests
+build_macosx_27:
+  <<: *build_job
+  variables: &macosx_27_build_variables
+    PYTHON_VERSION: "2.7"
+    WHEEL_TAG: "py27"
+  tags:
+    - conda-macosx
+
+test_macosx_27:
+  <<: *test_job
+  variables: *macosx_27_build_variables
+  dependencies:
+    - build_macosx_27
+  tags:
+    - conda-macosx
+
+
+# Mac OSX + Python 3.4: Builds and tests
+build_macosx_34:
+  <<: *build_job
+  variables: &macosx_34_build_variables
+    PYTHON_VERSION: "3.4"
+    WHEEL_TAG: "py3"
+  tags:
+    - conda-macosx
+
+test_macosx_34:
+  <<: *test_job
+  variables: *macosx_34_build_variables
+  dependencies:
+    - build_macosx_34
+  tags:
+    - conda-macosx
+
+
+# Mac OSX + Python 3.5: Builds and tests
+build_macosx_35:
+  <<: *build_job
+  variables: &macosx_35_build_variables
+    PYTHON_VERSION: "3.5"
+    WHEEL_TAG: "py3"
+  tags:
+    - conda-macosx
+
+test_macosx_35:
+  <<: *test_job
+  variables: *macosx_35_build_variables
+  dependencies:
+    - build_macosx_35
+  tags:
+    - conda-macosx
diff --git a/README.rst b/README.rst
index 5c3c067..2d7208e 100644
--- a/README.rst
+++ b/README.rst
@@ -23,12 +23,13 @@
 
 
 
-
 =======================================================
 CUHK Face Sketch FERET Database (CUFSF)
 =======================================================
 
-This package contains the access API and descriptions for the `CUHK Face Sketch FERET Database (CUFSF) <http://mmlab.ie.cuhk.edu.hk/archive/cufsf/>`. 
+This package is part of the signal-processing and machine learning toolbox
+Bob_.
+This package contains the access API and descriptions for the `CUHK Face Sketch Database (CUFS) <http://mmlab.ie.cuhk.edu.hk/archive/facesketch.html>`. 
 The actual raw data for the database should be downloaded from the original URL. 
 This package only contains the Bob accessor methods to use the DB directly from python, with the original protocol of the database.
 
@@ -36,60 +37,24 @@ CUHK Face Sketch FERET Database (CUFSF) is for research on face sketch synthesis
 It includes 1194 faces from the FERET database with their respective sketches (drawn by an artist based on a photo of the FERET database).
 
 
-You would normally not install this package unless you are maintaining it. 
-What you would do instead is to tie it in at the package you need to **use** it.
-There are a few ways to achieve this:
-
-1. You can add this package as a requirement at the ``setup.py`` for your own
-   `satellite package
-   <https://github.com/idiap/bob/wiki/Virtual-Work-Environments-with-Buildout>`_
-   or to your Buildout ``.cfg`` file, if you prefer it that way. With this
-   method, this package gets automatically downloaded and installed on your
-   working environment, or
-
-2. You can manually download and install this package using commands like
-   ``easy_install`` or ``pip``.
-
-The package is available in two different distribution formats:
-
-1. You can download it from `PyPI <http://pypi.python.org/pypi>`_, or
-
-2. You can download it in its source form from `its git repository
-   <https://github.com/bioidiap/bob.db.cuhk_cufsf>`_.
-
-You can mix and match points 1/2 and a/b above based on your requirements. Here
-are some examples:
-
-Modify your setup.py and download from PyPI
-===========================================
+Installation
+------------
 
-That is the easiest. Edit your ``setup.py`` in your satellite package and add
-the following entry in the ``install_requires`` section (note: ``...`` means
-`whatever extra stuff you may have in-between`, don't put that on your
-script)::
+Follow our `installation`_ instructions. Then, using the Python interpreter
+provided by the distribution, bootstrap and buildout this package::
 
-    install_requires=[
-      ...
-      "bob.db.cuhk_cufsf",
-    ],
+  $ python bootstrap-buildout.py
+  $ ./bin/buildout
 
-Proceed normally with your ``boostrap/buildout`` steps and you should be all
-set. That means you can now import the ``bob.db.cuhk_cufsf`` namespace into your scripts.
 
-Modify your buildout.cfg and download from git
-==============================================
+Contact
+-------
 
-You will need to add a dependence to `mr.developer
-<http://pypi.python.org/pypi/mr.developer/>`_ to be able to install from our
-git repositories. Your ``buildout.cfg`` file should contain the following
-lines::
+For questions or reporting issues to this software package, contact our
+development `mailing list`_.
 
-  [buildout]
-  ...
-  extensions = mr.developer
-  auto-checkout = *
-  eggs = bob.db.cuhk_cufsf
 
-  [sources]
-  bob.db.cuhk_cufsf = git https://github.com/bioidiap/bob.db.cuhk_cufsf.git
-  ...
+.. Place your references here:
+.. _bob: https://www.idiap.ch/software/bob
+.. _installation: https://gitlab.idiap.ch/bob/bob/wikis/Installation
+.. _mailing list: https://groups.google.com/forum/?fromgroups#!forum/bob-devel
diff --git a/bob/db/cuhk_cufsf/create.py b/bob/db/cuhk_cufsf/create.py
index b8a9617..1e744e7 100644
--- a/bob/db/cuhk_cufsf/create.py
+++ b/bob/db/cuhk_cufsf/create.py
@@ -25,6 +25,7 @@ import os
 
 from .models import *
 from utils import FERETWrapper
+import pkg_resources
 
 def add_clients_files_annotations(session, verbose = True):
 
@@ -63,8 +64,8 @@ def add_clients_files_annotations(session, verbose = True):
                 ))                
     output[client_id_offset] = [file_id_offset]
 
-    r_annotations = open("bob/db/cuhk_cufsf/data/sketch_points/{0}.3pts".format(feret_clients[c][0])).readlines()[0].rstrip("\n").split(" ")
-    l_annotations = open("bob/db/cuhk_cufsf/data/sketch_points/{0}.3pts".format(feret_clients[c][0])).readlines()[1].rstrip("\n").split(" ")    
+    r_annotations = open(pkg_resources.resource_filename(__name__, "data/sketch_points/{0}.3pts".format(feret_clients[c][0]))).readlines()[0].rstrip("\n").split(" ") 
+    l_annotations = open(pkg_resources.resource_filename(__name__, "data/sketch_points/{0}.3pts".format(feret_clients[c][0]))).readlines()[1].rstrip("\n").split(" ")
     session.add(Annotation(file_id = file_id_offset, re_x=r_annotations[0], re_y=r_annotations[1], le_x=l_annotations[0], le_y=l_annotations[1] ))
 
     
@@ -77,7 +78,7 @@ def add_clients_files_annotations(session, verbose = True):
                      modality="photo"
                 ))
     output[client_id_offset].append(file_id_offset)
-    annotations = open("bob/db/cuhk_cufsf/data/photo_points/{0}.tif.pos".format(feret_clients[c][1])).readlines()[0].rstrip("\n").split(" ")
+    annotations = open(pkg_resources.resource_filename(__name__, "data/photo_points/{0}.tif.pos".format(feret_clients[c][1]))).readlines()[0].rstrip("\n").split(" ")
     session.add(Annotation(file_id = file_id_offset, re_x=annotations[2], re_y=annotations[3], le_x=annotations[0], le_y=annotations[1] ))
     
 
diff --git a/bob/db/cuhk_cufsf/models.py b/bob/db/cuhk_cufsf/models.py
index bfd6ec9..46fe8d4 100644
--- a/bob/db/cuhk_cufsf/models.py
+++ b/bob/db/cuhk_cufsf/models.py
@@ -140,9 +140,9 @@ class File(Base, bob.db.base.File):
 
   def __init__(self, id, image_name, client_id, modality):
     # call base class constructor
-    bob.db.base.File.__init__(self, file_id = id, client_id = client_id, path = image_name)
+    bob.db.base.File.__init__(self, file_id = id, path = image_name)
     self.modality = modality
-
+    self.client_id = client_id
   
   def annotations(self, annotation_type="eyes_center"):
     if annotation_type=="eyes_center":
diff --git a/bob/db/cuhk_cufsf/query.py b/bob/db/cuhk_cufsf/query.py
index 68a8e2a..7c14e69 100644
--- a/bob/db/cuhk_cufsf/query.py
+++ b/bob/db/cuhk_cufsf/query.py
@@ -60,13 +60,18 @@ class Database(bob.db.base.SQLiteDatabase):
 
 
   def original_file_name(self, file, check_existence = True):
-    """This function returns the original file name for the given File object.
-    Keyword parameters:
-    file : :py:class:`File` or a derivative
+    """
+    This function returns the original file name for the given File object.
+    
+    **Parameters**
+    
+    file: :py:class:`File`
       The File objects for which the file name should be retrieved
-    check_existence : bool
+      
+    check_existence: bool
       Check if the original file exists? IGNORED: ALWAYS CHECK
-    Return value : str
+      
+    **Return**
       The original file name for the given File object
     """
 
@@ -95,11 +100,15 @@ class Database(bob.db.base.SQLiteDatabase):
 
 
   def annotations(self, file, annotation_type="eyes_center"):
-    """This function returns the annotations for the given file id as a dictionary.
-    Keyword parameters:
-    file : :py:class:`bob.db.base.File` or one of its derivatives
+    """
+    This function returns the annotations for the given file id as a dictionary.
+    
+    **Parameters**
+    
+    file: :py:class:`bob.db.base.File`
       The File object you want to retrieve the annotations for,
-    Return value:
+
+    **Return**
       A dictionary of annotations, for face images usually something like {'leye':(le_y,le_x), 'reye':(re_y,re_x), ...},
       or None if there are no annotations for the given file ID (which is the case in this base class implementation).
     """    
@@ -129,7 +138,7 @@ class Database(bob.db.base.SQLiteDatabase):
     query = query.filter(bob.db.cuhk_cufsf.Protocol_File_Association.protocol.in_(protocols))
     query = query.filter(bob.db.cuhk_cufsf.Protocol_File_Association.purpose.in_(purposes))
 
-    if model_ids is not None:     
+    if model_ids is not None and not 'probe' in purposes:
       if type(model_ids) is not list and type(model_ids) is not tuple:
         model_ids = [model_ids]
      
diff --git a/bob/db/cuhk_cufsf/utils.py b/bob/db/cuhk_cufsf/utils.py
index 509aafd..c7dc76d 100644
--- a/bob/db/cuhk_cufsf/utils.py
+++ b/bob/db/cuhk_cufsf/utils.py
@@ -11,6 +11,8 @@ This file has some utilities to deal with the files provided by the database
 import os
 import numpy
 import bob.db.arface
+import pkg_resources
+
 
 def read_annotations(file_name):
   """
@@ -42,7 +44,7 @@ class FERETWrapper():
   """
 
   def __init__(self, 
-      photo_file_name=os.path.join(os.path.curdir,"bob","db","cuhk_cufsf","data","feret_filenames.txt")
+      photo_file_name = pkg_resources.resource_filename(__name__, "data/feret_filenames.txt")
    ):
 
     self.m_photo_file_name  = photo_file_name
diff --git a/doc/extra-intersphinx.txt b/doc/extra-intersphinx.txt
new file mode 100644
index 0000000..676c4b7
--- /dev/null
+++ b/doc/extra-intersphinx.txt
@@ -0,0 +1 @@
+bob.bio.base
diff --git a/doc/guide.rst b/doc/guide.rst
index 6262a78..4b9870d 100644
--- a/doc/guide.rst
+++ b/doc/guide.rst
@@ -13,7 +13,7 @@ The actual raw data for the database should be downloaded from the original URL.
 The Database Interface
 ----------------------
 
-The :py:class:`bob.db.cuhk_cufsf.Database` complies with the standard biometric verification database as described in :ref:`commons`, implementing both interfaces :py:class:`bob.db.verification.utils.SQLiteDatabase` and :py:class:`bob.db.verification.utils.ZTDatabase`.
+The :py:class:`bob.db.cuhk_cufsf.Database`  complies with the standard biometric verification database as described in `bob.db.base <bob.db.base>`_, implementing the interface :py:class:`bob.db.base.SQLiteDatabase`.
 
 
 CUHK CUFSF Protocols
diff --git a/doc/nitpick-exceptions.txt b/doc/nitpick-exceptions.txt
new file mode 100644
index 0000000..5c331f3
--- /dev/null
+++ b/doc/nitpick-exceptions.txt
@@ -0,0 +1,2 @@
+py:class sqlalchemy.ext.declarative.api.Base
+py:exc ValueError
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..68a4642
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+setuptools
+six
+bob.blitz
+bob.core
+bob.io.base
+bob.db.base
diff --git a/setup.py b/setup.py
index eba4eca..88fa1a4 100644
--- a/setup.py
+++ b/setup.py
@@ -19,13 +19,16 @@
 
 from setuptools import setup, find_packages
 
+from bob.extension.utils import load_requirements
+install_requires = load_requirements()
+
 setup(
 
     name='bob.db.cuhk_cufsf',
     version='0.0.0a1',
     description='CUHK Face Sketch FERET Database (CUFSF)',
     url='',
-    license='GPLv3',
+    license='BSD',
     keywords = "",
     author='Tiago de Freitas Pereira',
     author_email='tiago.pereira@idiap.ch',
@@ -35,10 +38,7 @@ setup(
     include_package_data=True,
     zip_safe = False,
 
-    install_requires=[
-      'setuptools',
-      'bob.db.verification.utils' 
-    ],
+    install_requires=install_requires,
 
     namespace_packages = [
       'bob',
@@ -55,7 +55,7 @@ setup(
     classifiers = [
       'Development Status :: 4 - Beta',
       'Intended Audience :: Education',
-      'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
+      'License :: OSI Approved :: BSD License',
       'Natural Language :: English',
       'Programming Language :: Python',
       'Programming Language :: Python :: 3',
-- 
GitLab