From 12fe9211f36dc1024f141e31d3bf8a8d27915753 Mon Sep 17 00:00:00 2001 From: Lingxian Kong Date: Mon, 14 Aug 2017 13:31:24 +1200 Subject: [PATCH] Re-orginze documentation Change-Id: Ic0903cb9288e01682df01c3e69f934ed40c53a4f --- README.rst | 298 +----------------------------------- doc/source/conf.py | 11 +- doc/source/index.rst | 29 +++- doc/source/installation.rst | 43 +----- doc/source/quick_start.rst | 293 +++++++++++++++++++++++++++++++++++ doc/source/readme.rst | 1 - doc/source/usage.rst | 7 - 7 files changed, 333 insertions(+), 349 deletions(-) create mode 100644 doc/source/quick_start.rst delete mode 100644 doc/source/readme.rst delete mode 100644 doc/source/usage.rst diff --git a/README.rst b/README.rst index 7bc30a66..68cc2a7f 100644 --- a/README.rst +++ b/README.rst @@ -19,299 +19,5 @@ plugin mechanism. * Documentation: http://docs.openstack.org/developer/qinling * Source: http://git.openstack.org/cgit/openstack/qinling * Features: https://blueprints.launchpad.net/qinling -* Bugs: http://bugs.launchpad.net/qinling -* IRC channel: #openstack-qinling - -Quick Start -~~~~~~~~~~~ - -Installation ------------- - -A fast and simple way to try Qinling is to create a Vagrant VM including all -related components and dependencies of Qinling service. For your convenience, -Qinling team already provide a Vagrantfile in ``tools/vagrant`` folder. - -Qinling is a FaaS implemented on top of container orchestration system such as -Kubernetes, Swarm, etc. Particularly, Kubernetes is a reference backend -considering its popularity. So, you need to setup Kubernetes first before -installing Qinling. The easiest way to setup Kubernetes is to use `Minikube -`_, it runs a -single-node Kubernetes cluster inside a VM alongside Qinling vagrant VM, so -they can communicate with each other without any network configuration. - -.. note:: - - In order to manage resources on Kubernetes, it is recommended to install - `kubectl `_ - command line tool. - -Qinling can work with OpenStack Keystone for authentication, or it can work -without authentication at all. By default, authentication is disabled, config -``auth_enable = True`` to enable authentication. - -After Kubernetes installation, perform the following commands on your local -host. - -#. Setup HTTP proxy to access the Kubernetes API: - - .. code-block:: console - - $ kubectl proxy --accept-hosts='.*' --address='0.0.0.0' - - Starting to serve on [::]:8001 - - .. end - -#. Clone Qinling repo and go to ``vagrant`` directory: - - .. code-block:: console - - $ git clone https://github.com/LingxianKong/qinling.git - $ cd qinling/tools/vagrant - - .. end - -#. Modify Qinling sample config file according to your own environment. Suppose - your IP address of your local host is ``192.168.200.50``, default Kubernetes - API HTTP proxy port is ``8001``, and Qinling vagrant VM IP address is - ``192.168.33.18`` (the default value in ``Vagrantfile``): - - .. code-block:: console - - $ sed -i 's/KUBERNETES_API_HOST/192.168.200.50/' qinling.conf.sample - $ sed -i 's/KUBERNETES_API_PORT/8001/' qinling.conf.sample - $ sed -i 's/QINLING_API_ADDRESS/192.168.33.18/' qinling.conf.sample - - .. end - -#. Now, start Qinling vagrant VM: - - .. code-block:: console - - $ vagrant --version - Vagrant 1.9.1 - $ vagrant up - ... - ==> default: INFO [alembic.runtime.migration] Context impl MySQLImpl. - ==> default: INFO [alembic.runtime.migration] Will assume non-transactional DDL. - ==> default: INFO [alembic.runtime.migration] Running upgrade -> 001, Pike release - - .. end - - If you see message like the above, congratulations! - -Getting started with Qinling ----------------------------- - -**Currently, you can interact with Qinling using python-qinlingclient or -sending RESTful API directly. Both ways are described in this guide.** - -``httpie`` is a convenient tool to send HTTP request, make sure you installed -``httpie`` via ``pip install httpie`` before playing with Qinling. - -If you prefer to use CLI, please make sure python-qinlingclient is installed. - -Perform following commands on your local host, the process will create -runtime/function/execution in Qinling. - -#. (Optional) Prepare a docker image including development environment for a - specific programming language. For your convenience, I already build one - (``lingxiankong/python-runtime``) in my docker hub account that you could - directly use to create runtime in Qinling. Only ``Python 2`` runtime is - supported for now, but it is very easy to add another program language - support. If you indeed want to build a new image, run the following commands - in ``qinling`` repo directory, replace ``DOCKER_USER`` with your own docker - hub username: - - .. code-block:: console - - $ cd runtimes/python2 - $ docker build -t DOCKER_USER/python-runtime . - $ docker push DOCKER_USER/python-runtime - - .. end - -#. Create runtime. A runtime in Qinling is running environment for a specific - language, this resource is supposed to be created/deleted/updated by cloud - operator. After creation, check the runtime status is ``available``: - - .. code-block:: console - - $ http POST http://192.168.33.18:7070/v1/runtimes name=python2.7 \ - image=DOCKER_USER/python-runtime - - HTTP/1.1 201 Created - Connection: keep-alive - Content-Length: 194 - Content-Type: application/json - Date: Fri, 12 May 2017 04:37:08 GMT - - { - "created_at": "2017-05-12 04:37:08.129860", - "id": "c1d78623-56bf-4487-9a72-1299b2c55e65", - "image": "DOCKER_USER/python-runtime", - "name": "python2.7", - "project_id": "default", - "status": "creating" - } - - $ http GET http://192.168.33.18:7070/v1/runtimes/c1d78623-56bf-4487-9a72-1299b2c55e65 - - HTTP/1.1 200 OK - Connection: keep-alive - Content-Length: 246 - Content-Type: application/json - Date: Fri, 12 May 2017 04:37:50 GMT - - { - "created_at": "2017-05-12 04:37:08", - "description": null, - "id": "c1d78623-56bf-4487-9a72-1299b2c55e65", - "image": "DOCKER_USER/python-runtime", - "name": "python2.7", - "project_id": "default", - "status": "available", - "updated_at": "2017-05-12 04:37:08" - } - - .. end - - Using CLI: - - .. code-block:: console - - $ openstack runtime create python2.7 DOCKER_USER/python-runtime - +------------+--------------------------------------+ - | Field | Value | - +------------+--------------------------------------+ - | id | c1d78623-56bf-4487-9a72-1299b2c55e65 | - | name | python2.7 | - | image | DOCKER_USER/python-runtime | - | project_id | default | - | status | available | - | created_at | 2017-05-12 04:37:08.129860 | - | updated_at | | - +------------+--------------------------------------+ - - .. end - -#. Create a customized function package: - - .. code-block:: console - - $ mkdir ~/qinling_test - $ cat < ~/qinling_test/main.py - import requests - def main(): - r = requests.get('https://api.github.com/events') - return len(r.json()) - if __name__ == '__main__': - main() - EOF - $ pip install requests -t ~/qinling_test - $ cd ~/qinling_test - $ zip -r ~/qinling_test/qinling_test.zip ./* - - .. end - -#. Create function, ``runtime_id`` comes from the output of above command: - - .. code-block:: console - - $ http -f POST http://192.168.33.18:7070/v1/functions name=github_test \ - runtime_id=c1d78623-56bf-4487-9a72-1299b2c55e65 \ - code='{"package": "true"}' \ - package@~/qinling_test/qinling_test.zip - - HTTP/1.1 201 Created - Connection: keep-alive - Content-Length: 234 - Content-Type: application/json - Date: Fri, 12 May 2017 04:49:59 GMT - - { - "code": { - "package": "true" - }, - "created_at": "2017-05-12 04:49:59.659345", - "description": null, - "entry": "main.main", - "id": "352e4c02-3c6b-4860-9b85-f72344b1f986", - "name": "github_test", - "runtime_id": "c1d78623-56bf-4487-9a72-1299b2c55e65" - } - - .. end - - Using CLI: - - .. code-block:: console - - $ openstack function create github_test \ - c1d78623-56bf-4487-9a72-1299b2c55e65 \ - '{"source": "package"}' \ - --package ~/qinling_test/qinling_test.zip - +------------+--------------------------------------+ - | Field | Value | - +------------+--------------------------------------+ - | id | 352e4c02-3c6b-4860-9b85-f72344b1f986 | - | name | github_test | - | count | 0 | - | code | {u'source': u'package'} | - | runtime_id | c1d78623-56bf-4487-9a72-1299b2c55e65 | - | entry | main.main | - | created_at | 2017-05-12 04:49:59.659345 | - | updated_at | | - +------------+--------------------------------------+ - - .. end - -#. Invoke the function by specifying ``function_id``: - - .. code-block:: console - - $ http POST http://192.168.33.18:7070/v1/executions \ - function_id=352e4c02-3c6b-4860-9b85-f72344b1f986 - - HTTP/1.1 201 Created - Connection: keep-alive - Content-Length: 255 - Content-Type: application/json - Date: Thu, 11 May 2017 23:46:12 GMT - - { - "created_at": "2017-05-12 04:51:10", - "function_id": "352e4c02-3c6b-4860-9b85-f72344b1f986", - "id": "80cd55be-d369-49b8-8bd5-e0bfc1d20d25", - "input": null, - "output": "{\"result\": 30}", - "status": "success", - "sync": true, - "updated_at": "2017-05-12 04:51:23" - } - - .. end - - Using CLI: - - .. code-block:: console - - $ openstack function execution create 352e4c02-3c6b-4860-9b85-f72344b1f986 - +-------------+------------------------------------------------------------+ - | Field | Value | - +-------------+------------------------------------------------------------+ - | id | 80cd55be-d369-49b8-8bd5-e0bfc1d20d25 | - | function_id | 352e4c02-3c6b-4860-9b85-f72344b1f986 | - | input | {} | - | output | {"result": {"duration": 1.2511260509490967, "output": 30}} | - | status | success | - | sync | True | - | created_at | 2017-05-12 04:51:10 | - | updated_at | 2017-05-12 04:51:23 | - +-------------+------------------------------------------------------------+ - - .. end - - If you invoke the same function again, you will find it is much faster - thanks to Qinling cache mechanism. +* Bug Track: http://bugs.launchpad.net/qinling +* IRC channel on Freenode: #openstack-qinling diff --git a/doc/source/conf.py b/doc/source/conf.py index 9ff48f41..84a1e822 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import datetime as dt import os import sys @@ -37,8 +38,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'qinling' -copyright = u'2016, OpenStack Foundation' +project = u'Qinling' +copyright = u"%d, OpenStack Foundation" % dt.datetime.now().year # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True @@ -54,9 +55,9 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] +html_theme_path = [] +html_theme = "default" +html_static_path = [] # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project diff --git a/doc/source/index.rst b/doc/source/index.rst index f1fbe18f..a0065c53 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -3,17 +3,36 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to qinling's documentation! -======================================================== +Welcome to Qinling's documentation! +=================================== -Contents: +.. note:: + + Qinling (is pronounced "tʃinliŋ") refers to Qinling Mountains in southern + Shaanxi Province in China. The mountains provide a natural boundary between + North and South China and support a huge variety of plant and wildlife, some + of which is found nowhere else on Earth. + +Qinling is Function as a Service for OpenStack. This project aims to provide a +platform to support serverless functions (like AWS Lambda). Qinling supports +different container orchestration platforms (Kubernetes/Swarm, etc.) and +different function package storage backends (local/Swift/S3) by nature using +plugin mechanism. + +* Free software: Apache license +* Documentation: http://qinling.readthedocs.io/ +* Source: http://git.openstack.org/cgit/openstack/qinling +* Features: https://blueprints.launchpad.net/qinling +* Bug Track: http://bugs.launchpad.net/qinling +* IRC channel on Freenode: #openstack-qinling + +Table of Contents: .. toctree:: :maxdepth: 2 - readme + quick_start installation - usage contributing Indices and tables diff --git a/doc/source/installation.rst b/doc/source/installation.rst index d4bb70b8..6f4813c5 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -2,7 +2,7 @@ Qinling Installation Guide ========================== Prerequisites -------------- +~~~~~~~~~~~~~ It is necessary to install some specific system libs for installing Qinling. They can be installed on most popular operating system using their package @@ -29,7 +29,7 @@ with OpenStack.** In case of OpenStack, it works **only on Keystone v3**, make sure **Keystone v3** is installed. Installation ------------- +~~~~~~~~~~~~ First of all, clone the repo and go to the repo directory:: @@ -68,7 +68,7 @@ that it doesn’t actually install anything. Instead, it creates a special source code. Before the first run --------------------- +~~~~~~~~~~~~~~~~~~~~ After installation you will see **qinling-server** and **qinling-db-manage** commands in your environment, either in system or virtual environment. @@ -105,21 +105,21 @@ Please use sync_db script described below instead for database initialization. $ python tools/sync_db.py --config-file Running Qinling API server --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ To run Qinling API server perform the following command in a shell:: $ qinling-server --server api --config-file Running Qinling Engines ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ To run Qinling Engine perform the following command in a shell:: $ qinling-server --server engine --config-file Running Qinling Task Executors ------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To run Qinling Task Executor instance perform the following command in a shell:: $ qinling-server --server executor --config-file @@ -128,7 +128,7 @@ Note that at least one Engine instance and one Executor instance should be running so that workflow tasks are processed by Qinling. Running Multiple Qinling Servers Under the Same Process -------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To run more than one server (API, Engine, or Task Executor) on the same process, perform the following command in a shell:: @@ -142,34 +142,7 @@ Qinling servers are launched on the same process. Otherwise, messages do not get delivered if the Qinling servers are launched on different processes because the "fake" transport is using an in process queue. -Qinling And Docker ------------------- -Please first refer `installation steps for docker `_. -To build the image from the qinling source, change directory to the root -directory of the Qinling git repository and run:: - - $ docker build -t . - -In case you want pre-built image, you can download it from `openstack tarballs source `_. - -To load this image to docker registry, please run following command:: - - $ docker load -i '' - -The Qinling Docker image is configured to store the database in the user's home -directory. For persistence of these data, you may want to keep this directory -outside of the container. This may be done by the following steps:: - - $ sudo mkdir '' - $ docker run -it -v '':/home/qinling - -More about docker: https://www.docker.com/ - -**NOTE:** This docker image uses **SQLite** database. So, it cannot be used for -production environment. If you want to use this for production environment, -then put customized qinling.conf to ''. - Qinling Client Installation ---------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Please refer to :doc:`Qinling Client / CLI Guide ` diff --git a/doc/source/quick_start.rst b/doc/source/quick_start.rst new file mode 100644 index 00000000..a77202b6 --- /dev/null +++ b/doc/source/quick_start.rst @@ -0,0 +1,293 @@ +Quick Start +=========== + +Installation +~~~~~~~~~~~~ + +A fast and simple way to try Qinling is to create a Vagrant VM including all +related components and dependencies of Qinling service. For your convenience, +Qinling team already provide a Vagrantfile in ``tools/vagrant`` folder. + +Qinling is a FaaS implemented on top of container orchestration system such as +Kubernetes, Swarm, etc. Particularly, Kubernetes is a reference backend +considering its popularity. So, you need to setup Kubernetes first before +installing Qinling. The easiest way to setup Kubernetes is to use `Minikube +`_, it runs a +single-node Kubernetes cluster inside a VM alongside Qinling vagrant VM, so +they can communicate with each other without any network configuration. + +.. note:: + + In order to manage resources on Kubernetes, it is recommended to install + `kubectl `_ + command line tool. + +Qinling can work with OpenStack Keystone for authentication, or it can work +without authentication at all. By default, authentication is disabled, config +``auth_enable = True`` to enable authentication. + +After Kubernetes installation, perform the following commands on your local +host. + +#. Setup HTTP proxy to access the Kubernetes API: + + .. code-block:: console + + $ kubectl proxy --accept-hosts='.*' --address='0.0.0.0' + + Starting to serve on [::]:8001 + + .. end + +#. Clone Qinling repo and go to ``vagrant`` directory: + + .. code-block:: console + + $ git clone https://github.com/LingxianKong/qinling.git + $ cd qinling/tools/vagrant + + .. end + +#. Modify Qinling sample config file according to your own environment. Suppose + your IP address of your local host is ``192.168.200.50``, default Kubernetes + API HTTP proxy port is ``8001``, and Qinling vagrant VM IP address is + ``192.168.33.18`` (the default value in ``Vagrantfile``): + + .. code-block:: console + + $ sed -i 's/KUBERNETES_API_HOST/192.168.200.50/' qinling.conf.sample + $ sed -i 's/KUBERNETES_API_PORT/8001/' qinling.conf.sample + $ sed -i 's/QINLING_API_ADDRESS/192.168.33.18/' qinling.conf.sample + + .. end + +#. Now, start Qinling vagrant VM: + + .. code-block:: console + + $ vagrant --version + Vagrant 1.9.1 + $ vagrant up + ... + ==> default: INFO [alembic.runtime.migration] Context impl MySQLImpl. + ==> default: INFO [alembic.runtime.migration] Will assume non-transactional DDL. + ==> default: INFO [alembic.runtime.migration] Running upgrade -> 001, Pike release + + .. end + + If you see message like the above, congratulations! + +Getting started with Qinling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Currently, you can interact with Qinling using python-qinlingclient or +sending RESTful API directly. Both ways are described in this guide.** + +``httpie`` is a convenient tool to send HTTP request, make sure you installed +``httpie`` via ``pip install httpie`` before playing with Qinling. + +If you prefer to use CLI, please make sure python-qinlingclient is installed. + +Perform following commands on your local host, the process will create +runtime/function/execution in Qinling. + +#. (Optional) Prepare a docker image including development environment for a + specific programming language. For your convenience, I already build one + (``lingxiankong/python-runtime``) in my docker hub account that you could + directly use to create runtime in Qinling. Only ``Python 2`` runtime is + supported for now, but it is very easy to add another program language + support. If you indeed want to build a new image, run the following commands + in ``qinling`` repo directory, replace ``DOCKER_USER`` with your own docker + hub username: + + .. code-block:: console + + $ cd runtimes/python2 + $ docker build -t DOCKER_USER/python-runtime . + $ docker push DOCKER_USER/python-runtime + + .. end + +#. Create runtime. A runtime in Qinling is running environment for a specific + language, this resource is supposed to be created/deleted/updated by cloud + operator. After creation, check the runtime status is ``available``: + + .. code-block:: console + + $ http POST http://192.168.33.18:7070/v1/runtimes name=python2.7 \ + image=DOCKER_USER/python-runtime + + HTTP/1.1 201 Created + Connection: keep-alive + Content-Length: 194 + Content-Type: application/json + Date: Fri, 12 May 2017 04:37:08 GMT + + { + "created_at": "2017-05-12 04:37:08.129860", + "id": "c1d78623-56bf-4487-9a72-1299b2c55e65", + "image": "DOCKER_USER/python-runtime", + "name": "python2.7", + "project_id": "default", + "status": "creating" + } + + $ http GET http://192.168.33.18:7070/v1/runtimes/c1d78623-56bf-4487-9a72-1299b2c55e65 + + HTTP/1.1 200 OK + Connection: keep-alive + Content-Length: 246 + Content-Type: application/json + Date: Fri, 12 May 2017 04:37:50 GMT + + { + "created_at": "2017-05-12 04:37:08", + "description": null, + "id": "c1d78623-56bf-4487-9a72-1299b2c55e65", + "image": "DOCKER_USER/python-runtime", + "name": "python2.7", + "project_id": "default", + "status": "available", + "updated_at": "2017-05-12 04:37:08" + } + + .. end + + Using CLI: + + .. code-block:: console + + $ openstack runtime create python2.7 DOCKER_USER/python-runtime + +------------+--------------------------------------+ + | Field | Value | + +------------+--------------------------------------+ + | id | c1d78623-56bf-4487-9a72-1299b2c55e65 | + | name | python2.7 | + | image | DOCKER_USER/python-runtime | + | project_id | default | + | status | available | + | created_at | 2017-05-12 04:37:08.129860 | + | updated_at | | + +------------+--------------------------------------+ + + .. end + +#. Create a customized function package: + + .. code-block:: console + + $ mkdir ~/qinling_test + $ cat < ~/qinling_test/main.py + import requests + def main(): + r = requests.get('https://api.github.com/events') + return len(r.json()) + if __name__ == '__main__': + main() + EOF + $ pip install requests -t ~/qinling_test + $ cd ~/qinling_test + $ zip -r ~/qinling_test/qinling_test.zip ./* + + .. end + +#. Create function, ``runtime_id`` comes from the output of above command: + + .. code-block:: console + + $ http -f POST http://192.168.33.18:7070/v1/functions name=github_test \ + runtime_id=c1d78623-56bf-4487-9a72-1299b2c55e65 \ + code='{"package": "true"}' \ + package@~/qinling_test/qinling_test.zip + + HTTP/1.1 201 Created + Connection: keep-alive + Content-Length: 234 + Content-Type: application/json + Date: Fri, 12 May 2017 04:49:59 GMT + + { + "code": { + "package": "true" + }, + "created_at": "2017-05-12 04:49:59.659345", + "description": null, + "entry": "main.main", + "id": "352e4c02-3c6b-4860-9b85-f72344b1f986", + "name": "github_test", + "runtime_id": "c1d78623-56bf-4487-9a72-1299b2c55e65" + } + + .. end + + Using CLI: + + .. code-block:: console + + $ openstack function create github_test \ + c1d78623-56bf-4487-9a72-1299b2c55e65 \ + '{"source": "package"}' \ + --package ~/qinling_test/qinling_test.zip + +------------+--------------------------------------+ + | Field | Value | + +------------+--------------------------------------+ + | id | 352e4c02-3c6b-4860-9b85-f72344b1f986 | + | name | github_test | + | count | 0 | + | code | {u'source': u'package'} | + | runtime_id | c1d78623-56bf-4487-9a72-1299b2c55e65 | + | entry | main.main | + | created_at | 2017-05-12 04:49:59.659345 | + | updated_at | | + +------------+--------------------------------------+ + + .. end + +#. Invoke the function by specifying ``function_id``: + + .. code-block:: console + + $ http POST http://192.168.33.18:7070/v1/executions \ + function_id=352e4c02-3c6b-4860-9b85-f72344b1f986 + + HTTP/1.1 201 Created + Connection: keep-alive + Content-Length: 255 + Content-Type: application/json + Date: Thu, 11 May 2017 23:46:12 GMT + + { + "created_at": "2017-05-12 04:51:10", + "function_id": "352e4c02-3c6b-4860-9b85-f72344b1f986", + "id": "80cd55be-d369-49b8-8bd5-e0bfc1d20d25", + "input": null, + "output": "{\"result\": 30}", + "status": "success", + "sync": true, + "updated_at": "2017-05-12 04:51:23" + } + + .. end + + Using CLI: + + .. code-block:: console + + $ openstack function execution create 352e4c02-3c6b-4860-9b85-f72344b1f986 + +-------------+------------------------------------------------------------+ + | Field | Value | + +-------------+------------------------------------------------------------+ + | id | 80cd55be-d369-49b8-8bd5-e0bfc1d20d25 | + | function_id | 352e4c02-3c6b-4860-9b85-f72344b1f986 | + | input | {} | + | output | {"result": {"duration": 1.2511260509490967, "output": 30}} | + | status | success | + | sync | True | + | created_at | 2017-05-12 04:51:10 | + | updated_at | 2017-05-12 04:51:23 | + +-------------+------------------------------------------------------------+ + + .. end + + If you invoke the same function again, you will find it is much faster + thanks to Qinling cache mechanism. \ No newline at end of file diff --git a/doc/source/readme.rst b/doc/source/readme.rst deleted file mode 100644 index a6210d3d..00000000 --- a/doc/source/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../README.rst diff --git a/doc/source/usage.rst b/doc/source/usage.rst deleted file mode 100644 index cfefcb19..00000000 --- a/doc/source/usage.rst +++ /dev/null @@ -1,7 +0,0 @@ -======== -Usage -======== - -To use qinling in a project:: - - import qinling