diff --git a/.travis-deploy-doc.sh b/.travis-deploy-doc.sh index 655557b..c16c8bb 100755 --- a/.travis-deploy-doc.sh +++ b/.travis-deploy-doc.sh @@ -10,7 +10,7 @@ if [[ "${TRAVIS_PULL_REQUEST}" == "false" && "${TRAVIS_BRANCH}" == "${DEPLOY_DOC fi chmod 600 .travis_ci_gh_pages_deploy_key eval `ssh-agent -s` - ssh-add .travis_ci_gh_pages_deploy_key + ssh-add .travis_ci_gh_pages_deploy_key < /dev/null rm -Rf gh-pages git clone --depth 1 git@github.com:${DEPLOY_DOC_TO_REPOSITORY}.git --depth 1 --branch=gh-pages gh-pages BUILT_DOCS_DIR=`cd docs/build/html && pwd` @@ -25,3 +25,4 @@ if [[ "${TRAVIS_PULL_REQUEST}" == "false" && "${TRAVIS_BRANCH}" == "${DEPLOY_DOC git push origin gh-pages fi fi +/usr/bin/killall python2 diff --git a/.travis-install.sh b/.travis-install.sh index eef217c..f5bc8ca 100755 --- a/.travis-install.sh +++ b/.travis-install.sh @@ -1,13 +1,16 @@ -#! /bin/sh +#! /bin/bash # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without any warranty. set -e +SAGE_IMAGE=`python2 -c "import setup; print setup.get_all_version_names('${SAGE_SERVER}index.html',${SAGE_AGE}, distribution='${UBUNTU_VERSION}')"` +echo "Obtaining Sage image:" +echo $SAGE_IMAGE cd $HOME -if [ ! -x SageMath/sage ] ; then +if [ ! -x SageMath/sage ] ; then rm -f SageMath.tar.bz2 - wget $SAGE_SERVER$SAGE_IMAGE -O SageMath.tar.bz2 + wget ${SAGE_SERVER}${SAGE_IMAGE} -O SageMath.tar.bz2 tar xf SageMath.tar.bz2 fi MAKE="make -j4" diff --git a/.travis-test.sh b/.travis-test.sh index 910faf4..434f519 100755 --- a/.travis-test.sh +++ b/.travis-test.sh @@ -1,10 +1,9 @@ #! /bin/sh -# Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright -# notice and this notice are preserved. This file is offered as-is, -# without any warranty. set -e + +mkdir -p $HOME/SageMath/build/pkgs +$HOME/SageMath/sage -pip install --upgrade -v -i https://pypi.python.org/pypi sagemath $HOME/SageMath/sage -pip install --upgrade --no-index -v . $HOME/SageMath/sage setup.py test (cd docs && $HOME/SageMath/sage -sh -c "make html") -$HOME/SageMath/sage -pip uninstall . +$HOME/SageMath/sage -pip uninstall sage_sample diff --git a/.travis.yml b/.travis.yml index c725191..b8b1f81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,30 @@ -# Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright -# notice and this notice are preserved. This file is offered as-is, -# without any warranty. language: python +python: 2.7 +dist: xenial matrix: include: - - env: CACHE_NAME=7.6 DEPLOY_DOC_FROM_BRANCH=master DEPLOY_DOC_TO_DIRECTORY=/ SAGE_SERVER=http://mirrors.xmission.com/sage/ SAGE_IMAGE=linux/64bit/sage-7.6-Ubuntu_12.04-x86_64.tar.bz2 - - env: CACHE_NAME=7.5.1 SAGE_SERVER=http://mirrors.xmission.com/sage/ SAGE_IMAGE=linux/64bit/sage-7.5.1-Ubuntu_12.04-x86_64.tar.bz2 + - env: CACHE_NAME=latest DEPLOY_DOC_FROM_BRANCH=master DEPLOY_DOC_TO_REPOSITORY=mmasdeu/sage_sample + DEPLOY_DOC_TO_DIRECTORY=doc/html SAGE_SERVER=http://mirrors.xmission.com/sage/linux/64bit/ + SAGE_AGE=0 UBUNTU_VERSION=Ubuntu_16.04-x86_64 + - env: CACHE_NAME=older SAGE_SERVER=http://mirrors.xmission.com/sage/linux/64bit/ SAGE_AGE=1 + UBUNTU_VERSION=Ubuntu_16.04-x86_64 + allow_failures: + - env: CACHE_NAME=older SAGE_SERVER=http://mirrors.xmission.com/sage/linux/64bit/ SAGE_AGE=1 + UBUNTU_VERSION=Ubuntu_16.04-x86_64 + install: -- ./.travis-install.sh +- "./.travis-install.sh" script: -- ./.travis-test.sh +- "./.travis-test.sh" cache: directories: - - $HOME/SageMath - - $HOME/.cache/matplotlib + - "$HOME/SageMath" + - "$HOME/.cache/matplotlib" timeout: 1000 before_cache: - rm -Rf $HOME/SageMath/logs $HOME/SageMath/.BUILDSTART after_success: -- ./.travis-deploy-doc.sh +- "./.travis-deploy-doc.sh" before_script: -- openssl aes-256-cbc -K $encrypted_f96cc3b3888c_key -iv $encrypted_f96cc3b3888c_iv +- openssl aes-256-cbc -K $encrypted_2f33c728c8dc_key -iv $encrypted_2f33c728c8dc_iv -in .travis_ci_gh_pages_deploy_key.enc -out .travis_ci_gh_pages_deploy_key -d || true diff --git a/.travis_ci_gh_pages_deploy_key.enc b/.travis_ci_gh_pages_deploy_key.enc index 10c8b74..6d32e82 100644 Binary files a/.travis_ci_gh_pages_deploy_key.enc and b/.travis_ci_gh_pages_deploy_key.enc differ diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..8dc223c --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,5 @@ +prune sage_sample +include VERSION +include sage_sample/*.py +include sage_sample/*.pyx + diff --git a/README.rst b/README.rst index da8ec40..561744c 100644 --- a/README.rst +++ b/README.rst @@ -2,12 +2,16 @@ Sage Sample Package =================== -This package is designed as as simple `SageMath `_ package +This package is designed as a simple `SageMath `_ package example to serve as a good practice reference for package developers. We follow python recommendations and adapt them to the SageMath community. You can find more advanced documentation on python package creation on `How To Package Your Python Code `_. +This is still a work in progress. Once this example will have +stabilized, the plan is to make a +`cookie cutter `_ +template out of it. Installation ------------ @@ -17,7 +21,7 @@ Local install from source Download the source from the git repository:: - $ git clone https://github.com/nthiery/sage_sample.git + $ git clone https://github.com/sagemath/sage_sample.git Change to the root directory and run:: @@ -25,14 +29,26 @@ Change to the root directory and run:: For convenience this package contains a [makefile](makefile) with this and other often used commands. Should you wish too, you can use the -shorthand: +shorthand:: $ make install Install from PyPI ^^^^^^^^^^^^^^^^^^ -TODO: distribute on PyPI. +Create an account at https://pypi.python.org/pypi + +Install ``twine`` in Sage:: + + $ sage -pip install --upgrade twine + +Create the distribution (you can also use ``bdist`` instead to create the built distribution instead of the source one):: + + $ python setup.py sdist + +Upload to PyPI:: + + $ twine upload dist/* -r pypi Usage ----- @@ -47,7 +63,7 @@ Setup ------ All packaging setup is done through ``setup.py``. To create your own package -follow the strcuture of the file and change the parameters accordingly. +follow the structure of the file and change the parameters accordingly. Source code ----------- @@ -73,7 +89,7 @@ configured in ``setup.py`` to run the tests:: This is just calling ``sage -t`` with appropriate flags. -Shorthand: +Shorthand:: $ make test @@ -86,19 +102,19 @@ The documentation of the package can be generated using Sage's $ cd docs $ sage -sh -c "make html" -Shorthand: +Shorthand:: $ make doc For this to work on your own package, make sure you follow the same structure as we do here: - * Create a ``docs`` folder containing the exact same ``Makefile`` and a ``source`` - folder. - * Copy and paste the ``docs/source/conf.py`` file from this package and update - the few project specific variables at the beginning of the file. - * Create an ``index.rst`` file as well as a ``.rst`` file for each - module you want on the documentation. +* Create a ``docs`` folder containing the exact same ``Makefile`` and a ``source`` + folder. +* Copy and paste the ``docs/source/conf.py`` file from this package and update + the few project specific variables at the beginning of the file. +* Create an ``index.rst`` file as well as a ``.rst`` file for each + module you want on the documentation. Travis CI integration --------------------- @@ -111,23 +127,22 @@ Travis CI system are included. https://docs.travis-ci.com/user/for-beginners explains how to enable automatic Travis CI builds for your GitHub-hosted project. -The scripts download and install binary releases (7.1-7.4) from a +The scripts download and install the last two binary releases from a SageMath mirror. Edit ``.travis-install.sh`` if some optional or experimental SageMath packages need to be installed prior to running -your package. Edit ``.travis.yml`` to change the list of SageMath -versions used. +your package. Automatically deploying documentation to GitHub pages using Travis CI --------------------------------------------------------------------- - * First do the steps described above to enable Travis CI integration - of your GitHub-hosted project. - - * If you don't already have GitHub pages for your project: Create and - checkout a branch ``gh-pages`` in your repository and put an empty - file ``.nojekyll`` in it. (See - https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/):: - Commit it and push it to GitHub:: +* First do the steps described above to enable Travis CI integration + of your GitHub-hosted project. + +* If you don't already have GitHub pages for your project: Create and + checkout a branch ``gh-pages`` in your repository and put an empty + file ``.nojekyll`` in it (see + https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/). + Then commit it and push it to GitHub:: $ git clone --single-branch --depth 1 https://github.com/USER/PROJECT.git gh-pages $ cd gh-pages @@ -138,38 +153,38 @@ Automatically deploying documentation to GitHub pages using Travis CI $ git commit -m "Initial commit" $ git push -u origin gh-pages $ cd .. - - * (Back in your working copy:) Generate a new ssh key pair with an - empty passphrase:: + +* (Back in your working copy:) Generate a new ssh key pair with an + empty passphrase:: $ ssh-keygen -t dsa -f .travis_ci_gh_pages_deploy_key - * Add the public ssh key (contents of the file - ``.travis_ci_gh_pages_deploy_key.pub``) to your GitHub repository - as a deploy key (Settings/Deploy keys/Add deploy key). - Title: Key for deploying documentation to GitHub pages. - Check Allow write access. +* Add the public ssh key (contents of the file + ``.travis_ci_gh_pages_deploy_key.pub``) to your GitHub repository + as a deploy key (Settings/Deploy keys/Add deploy key). + Title: Key for deploying documentation to GitHub pages. + Check Allow write access. - * Install the Travis CI command-line client from - https://github.com/travis-ci/travis.rb:: +* Install the Travis CI command-line client from + https://github.com/travis-ci/travis.rb:: $ gem install travis - - * Log in to Travis CI using your GitHub credentials:: + +* Log in to Travis CI using your GitHub credentials:: $ travis login - - * Encrypt the private ssh key, add the decryption keys - as secure environment variables to Travis CI, and - add code to ``.travis.yml`` to decrypt it:: + +* Encrypt the private ssh key, add the decryption keys + as secure environment variables to Travis CI, and + add code to ``.travis.yml`` to decrypt it:: $ travis encrypt-file .travis_ci_gh_pages_deploy_key --add before_script - * Add the encrypted private ssh key to the repository:: +* Add the encrypted private ssh key to the repository:: $ git add .travis_ci_gh_pages_deploy_key.enc - * Have git ignore the other keys (and the gh-pages directory):: +* Have git ignore the other keys (and the gh-pages directory):: $ echo >> .gitignore $ echo "/.travis_ci_gh_pages_deploy_key" >> .gitignore @@ -177,19 +192,19 @@ Automatically deploying documentation to GitHub pages using Travis CI $ echo "/gh-pages" >> .gitignore $ git add .gitignore - * Optionally, edit ``.travis.yml`` to adjust variables ``DEPLOY_DOC_...`` +* Optionally, edit ``.travis.yml`` to adjust variables ``DEPLOY_DOC_...`` - * Commit all changes to GitHub. The Travis CI build should then run - automatically and deploy it:: +* Commit all changes to GitHub. The Travis CI build should then run + automatically and deploy it:: $ git add .travis.yml $ git commit -m "Deploy built documentation to GitHub" $ git push - - * The deployed documentation will be available at: - https://USER.github.io/PROJECT/ - This can be customized by changing ``DEPLOY_DOC_TO_DIRECTORY=/`` - to another directory in ``.travis.yml`` - For example, setting ``DEPLOY_DOC_TO_DIRECTORY=doc/html`` will make - the deployed documentation available at: - https://USER.github.io/PROJECT/doc/html/ + +* The deployed documentation will be available at: + https://USER.github.io/PROJECT/ + This can be customized by changing ``DEPLOY_DOC_TO_DIRECTORY=/`` + to another directory in ``.travis.yml`` + For example, setting ``DEPLOY_DOC_TO_DIRECTORY=doc/html`` will make + the deployed documentation available at: + https://USER.github.io/PROJECT/doc/html/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c2552f5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +sagemath >= 1.2.8 +cython >= 0.26 diff --git a/sage_sample/one_cython_file.pyx b/sage_sample/one_cython_file.pyx new file mode 100644 index 0000000..d872f7e --- /dev/null +++ b/sage_sample/one_cython_file.pyx @@ -0,0 +1,3 @@ +# A sample cython file +def quick_question(int a): + return a + 1 diff --git a/sage_sample/ultimate_question.py b/sage_sample/ultimate_question.py index 3e65e0e..16ff553 100644 --- a/sage_sample/ultimate_question.py +++ b/sage_sample/ultimate_question.py @@ -23,6 +23,7 @@ - Viviane Pons: initial implementation """ from sage.combinat.combinat import catalan_number +from one_cython_file import quick_question def answer_to_ultimate_question(): r""" @@ -42,4 +43,4 @@ def answer_to_ultimate_question(): sage: answer_to_ultimate_question() == 42 True """ - return catalan_number(5) + return quick_question(catalan_number(5)) - 1 diff --git a/setup.py b/setup.py index 46bd63c..2db5ab8 100644 --- a/setup.py +++ b/setup.py @@ -1,45 +1,97 @@ ## -*- encoding: utf-8 -*- import os import sys +import re +import urllib2 from setuptools import setup from codecs import open # To open the README file with proper encoding from setuptools.command.test import test as TestCommand # for tests +from distutils.command import build as build_module +# Obtain the different Sage versions +def get_all_version_names(mirror_url, idx = None, distribution = 'Ubuntu_16.04-x86_64'): + if idx is None: + idx = 0 + else: + idx = int(idx) + site = urllib2.urlopen(mirror_url).read() + ans = re.findall('(sage-([0-9]*(?:\.[0-9]*)*)-%s.tar.bz2)'%distribution, site) + all_version_names = [] + for fname, ver in ans: + if fname not in all_version_names: + all_version_names.append(fname) + return all_version_names[idx] # Get information from separate files (README, VERSION) def readfile(filename): with open(filename, encoding='utf-8') as f: return f.read() +# Check the right Sage version +class build(build_module.build): + def run(self): + from sagemath.check_version import check_version + check_version(sage_required_version) + build_module.build.run(self) + + # For the tests class SageTest(TestCommand): def run_tests(self): - errno = os.system("sage -t --force-lib sage_sample") + errno = os.system("sage -t --force-lib sage_sample sage_sample/*.pyx") if errno != 0: sys.exit(1) -setup( - name = "sage_sample", - version = readfile("VERSION"), # the VERSION file is shared with the documentation - description='An example of a basic sage package', - long_description = readfile("README.rst"), # get the long description from the README - url='https://github.com/sagemath/sage_sample', - author='Matthias Koeppe, Sébastien Labbé, Viviane Pons, Nicolas M. Thiéry, ... with inspiration from many', - author_email='viviane.pons@lri.fr', # choose a main contact email - license='GPLv2+', # This should be consistent with the LICENCE file - classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable - 'Development Status :: 4 - Beta', - 'Intended Audience :: Science/Research', - 'Topic :: Software Development :: Build Tools', - 'Topic :: Scientific/Engineering :: Mathematics', - 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', - 'Programming Language :: Python :: 2.7', - ], # classifiers list: https://pypi.python.org/pypi?%3Aaction=list_classifiers - keywords = "SageMath packaging", - packages = ['sage_sample'], - cmdclass = {'test': SageTest} # adding a special setup command for tests -) +if __name__ == "__main__": + + # The next block is needed if there are cython files + from setuptools import Extension + from Cython.Build import cythonize + import Cython.Compiler.Options + from sage.env import sage_include_directories + from sage.misc.banner import version as sage_version + + + # Cython modules + ext_modules = [ + Extension('sage_sample.one_cython_file', + sources = [os.path.join('sage_sample','one_cython_file.pyx')], + include_dirs=sage_include_directories()) + ] + + # Specify the required Sage version + sage_required_version = u'>=8.9' + sage_current_version = sage_version() + py2 = bool('8.' in sage_current_version or '7.' in sage_current_version) + REQUIREMENTS = [i.strip() for i in open("requirements.txt").readlines()] + + setup( + name = "sage_sample", + version = readfile("VERSION"), # the VERSION file is shared with the documentation + description='An example of a basic sage package', + long_description = readfile("README.rst"), # get the long description from the README + url='https://github.com/sagemath/sage_sample', + author='Matthias Koeppe, Sébastien Labbé, Marc Masdeu, Viviane Pons, Nicolas M. Thiéry, ... with inspiration from many', + author_email='viviane.pons@lri.fr', # choose a main contact email + license='GPLv2+', # This should be consistent with the LICENCE file + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 4 - Beta', + 'Intended Audience :: Science/Research', + 'Topic :: Software Development :: Build Tools', + 'Topic :: Scientific/Engineering :: Mathematics', + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Programming Language :: Python :: 3.8', + ], # classifiers list: https://pypi.python.org/pypi?%3Aaction=list_classifiers + keywords = "SageMath packaging", + install_requires = REQUIREMENTS, # This ensures that Sage is installed + packages = ['sage_sample'], + # The following line is only needed if there are cython files present + ext_modules = cythonize(ext_modules) if py2 \ + else cythonize(ext_modules, compiler_directives={'language_level' : "3"}), + include_package_data = True, + cmdclass = {'build': build, 'test': SageTest} # adding a special setup command for tests + )