diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index c585a11..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-*.pyc
-docs/_build
-venv
-.venv/
-.eggs
-.cache
-.tox
-.python-version
-anosql.egg-info
-.idea/
-scratch/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 04aada7..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-language: python
-python:
-  - "2.7"
-  - "3.5"
-services:
-  - postgresql
-addons:
-  postgresql: "10"
-  apt:
-    packages:
-      - postgresql-10
-      - postgresql-client-10
-      - postgresql-server-dev-10
-install: "pip install tox"
-script: tox
diff --git a/MANIFEST.in b/MANIFEST.in
index bb3ec5f..9918be9 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1,7 @@
-include README.md
+include README.rst
+include CHANGELOG
+include LICENSE
+include tox.ini
+include test_requirements.txt
+recursive-include docs *.rst Makefile conf.py make.bat
+recursive-include tests *.csv *.sql
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..1d67dc5
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,267 @@
+Metadata-Version: 2.1
+Name: anosql
+Version: 1.0.2
+Summary: Easy SQL in Python
+Home-page: https://github.com/honza/anosql
+Author: Honza Pokorny
+Author-email: me@honza.ca
+Maintainer: Honza Pokorny
+Maintainer-email: me@honza.ca
+License: UNKNOWN
+Platform: UNKNOWN
+License-File: LICENSE
+
+anosql
+======
+
+**NOTICE**: This project is now deprecated in favor of `aiosql`_.
+
+Unfortunately, I no longer have the time to devote to this project, and aiosql
+is now a lot more popular.  I don't think it makes sense to maintain both.
+Open source ftw!  Thanks for your hard work, `Will`_!
+
+.. _aiosql: https://github.com/nackjicholson/aiosql
+.. _Will: https://github.com/nackjicholson
+
+.. image:: https://badge.fury.io/py/anosql.svg
+    :target: https://badge.fury.io/py/anosql
+    :alt: pypi package version
+
+.. image:: http://readthedocs.org/projects/anosql/badge/?version=latest
+    :target: http://anosql.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
+
+.. image:: https://travis-ci.org/honza/anosql.svg?branch=master
+    :target: https://travis-ci.org/honza/anosql
+    :alt: Travid build status
+
+A Python library for using SQL
+
+Inspired by the excellent `Yesql`_ library by Kris Jenkins.  In my mother
+tongue, *ano* means *yes*.
+
+If you are on python3.6+ or need ``anosql`` to work with ``asyncio``-based database drivers, see the related project, `aiosql <https://github.com/nackjicholson/aiosql>`_.
+
+Complete documentation is available at `Read The Docs <https://anosql.readthedocs.io/en/latest/>`_.
+
+Installation
+------------
+
+::
+
+  $ pip install anosql
+
+Usage
+-----
+
+Basics
+******
+
+Given a ``queries.sql`` file:
+
+.. code-block:: sql
+
+  -- name: get-all-greetings
+  -- Get all the greetings in the database
+  SELECT * FROM greetings;
+
+  -- name: select-users
+  -- Get all the users from the database,
+  -- and return it as a dict
+  SELECT * FROM USERS;
+
+We can issue SQL queries, like so:
+
+.. code-block:: python
+
+    import anosql
+    import psycopg2
+    import sqlite3
+
+    # PostgreSQL
+    conn = psycopg2.connect('...')
+    queries = anosql.from_path('queries.sql', 'psycopg2')
+
+    # Or, Sqlite3...
+    conn = sqlite3.connect('cool.db')
+    queries = anosql.from_path('queries.sql', 'sqlite3')
+
+    queries.get_all_greetings(conn)
+    # => [(1, 'en', 'Hi')]
+
+    queries.get_all_greetings.__doc__
+    # => Get all the greetings in the database
+
+    queries.get_all_greetings.sql
+    # => SELECT * FROM greetings;
+
+    queries.available_queries
+    # => ['get_all_greetings']
+
+
+Parameters
+**********
+
+Often, you want to change parts of the query dynamically, particularly values in
+the ``WHERE`` clause.  You can use parameters to do this:
+
+.. code-block:: sql
+
+  -- name: get-greetings-for-language
+  -- Get all the greetings in the database for given language
+  SELECT *
+  FROM greetings
+  WHERE lang = %s;
+
+And they become positional parameters:
+
+.. code-block:: python
+
+  visitor_language = "en"
+  queries.get_greetings_for_language(conn, visitor_language)
+  # => [(1, 'en', 'Hi')]
+
+
+One Row Query
+*************
+
+Often, you would expect at most one row from a query, so that getting a list
+is not convenient. Appending ``?`` to the query name makes it return either one
+tuple if it returned one row, or ``None`` in other cases.
+
+.. code-block:: sql
+
+  -- name: get-a-greeting?
+  -- Get a greeting based on its id
+  SELECT *
+  FROM greetings
+  WHERE id = %s;
+
+Then a tuple is returned:
+
+.. code-block:: python
+
+  queries.get_a_greeting(conn, 1)
+  # => (1, 'en', 'Hi')
+
+
+Named Parameters
+****************
+
+To make queries with many parameters more understandable and maintainable, you
+can give the parameters names:
+
+.. code-block:: sql
+
+  -- name: get-greetings-for-language-and-length
+  -- Get all the greetings in the database for given language and length
+  SELECT *
+  FROM greetings
+  WHERE lang = :lang
+  AND len(greeting) <= :length_limit;
+
+If you were writing a Postgresql query, you could also format the parameters as
+``%s(lang)`` and ``%s(length_limit)``.
+
+Then, call your queries like you would any Python function with named
+parameters:
+
+.. code-block:: python
+
+  visitor_language = "en"
+
+  greetings_for_texting = queries.get_greetings_for_language_and_length(
+                conn, lang=visitor_language, length_limit=140)
+
+Update/Insert/Delete
+********************
+
+In order to run ``UPDATE``, ``INSERT``, or ``DELETE`` statements, you need to
+add ``!`` to the end of your query name.  Anosql will then execute it properly.
+It will also return the number of affected rows.
+
+Insert queries returning autogenerated values
+*********************************************
+
+If you want the auto-generated primary key to be returned after you run an
+insert query, you can add ``<!`` to the end of your query name.
+
+.. code-block:: sql
+
+  -- name: create-user<!
+  INSERT INTO person (name) VALUES (:name)
+
+Adding custom query loaders.
+****************************
+
+Out of the box, ``anosql`` supports SQLite and PostgreSQL via the stdlib ``sqlite3`` database driver
+and ``psycopg2``. If you would like to extend ``anosql`` to communicate with other types of databases,
+you may create a driver adapter class and register it with ``anosql.core.register_driver_adapter()``.
+
+Driver adapters are duck-typed classes which adhere to the below interface. Looking at ``anosql/adapters`` package
+is a good place to get started by looking at how the ``psycopg2`` and ``sqlite3`` adapters work.
+
+To register a new loader::
+
+    import anosql
+    import anosql.core
+
+    class MyDbAdapter():
+        def process_sql(self, name, op_type, sql):
+            pass
+
+        def select(self, conn, sql, parameters):
+            pass
+
+        @contextmanager
+        def select_cursor(self, conn, sql, parameters):
+            pass
+
+        def insert_update_delete(self, conn, sql, parameters):
+            pass
+
+        def insert_update_delete_many(self, conn, sql, parameters):
+            pass
+
+        def insert_returning(self, conn, sql, parameters):
+            pass
+
+        def execute_script(self, conn, sql):
+            pass
+
+
+    anosql.core.register_driver_adapter("mydb", MyDbAdapter)
+
+    # To use make a connection to your db, and pass "mydb" as the db_type:
+    import mydbdriver
+    conn = mydbriver.connect("...")
+
+    anosql.load_queries("path/to/sql/", "mydb")
+    greetings = anosql.get_greetings(conn)
+
+    conn.close()
+
+If your adapter constructor takes arguments, you can register a function which can build
+your adapter instance::
+
+    def adapter_factory():
+        return MyDbAdapter("foo", 42)
+
+    anosql.register_driver_adapter("mydb", adapter_factory)
+
+Tests
+-----
+
+::
+
+   $ pip install tox
+   $ tox
+
+License
+-------
+
+BSD, short and sweet
+
+.. _Yesql: https://github.com/krisajenkins/yesql/
+
+
diff --git a/README.rst b/README.rst
index 78447aa..ec818b1 100644
--- a/README.rst
+++ b/README.rst
@@ -1,8 +1,18 @@
 anosql
 ======
 
+**NOTICE**: This project is now deprecated in favor of `aiosql`_.
+
+Unfortunately, I no longer have the time to devote to this project, and aiosql
+is now a lot more popular.  I don't think it makes sense to maintain both.
+Open source ftw!  Thanks for your hard work, `Will`_!
+
+.. _aiosql: https://github.com/nackjicholson/aiosql
+.. _Will: https://github.com/nackjicholson
+
 .. image:: https://badge.fury.io/py/anosql.svg
     :target: https://badge.fury.io/py/anosql
+    :alt: pypi package version
 
 .. image:: http://readthedocs.org/projects/anosql/badge/?version=latest
     :target: http://anosql.readthedocs.io/en/latest/?badge=latest
@@ -10,14 +20,16 @@ anosql
 
 .. image:: https://travis-ci.org/honza/anosql.svg?branch=master
     :target: https://travis-ci.org/honza/anosql
+    :alt: Travid build status
 
 A Python library for using SQL
 
 Inspired by the excellent `Yesql`_ library by Kris Jenkins.  In my mother
 tongue, *ano* means *yes*.
 
-If you are on python3.6+ or need ``anosql`` to work with ``asyncio`` based database drivers.
-See the related project `aiosql <https://github.com/nackjicholson/aiosql>`_.
+If you are on python3.6+ or need ``anosql`` to work with ``asyncio``-based database drivers, see the related project, `aiosql <https://github.com/nackjicholson/aiosql>`_.
+
+Complete documentation is available at `Read The Docs <https://anosql.readthedocs.io/en/latest/>`_.
 
 Installation
 ------------
@@ -40,7 +52,7 @@ Given a ``queries.sql`` file:
   -- Get all the greetings in the database
   SELECT * FROM greetings;
 
-  -- name: $select-users
+  -- name: select-users
   -- Get all the users from the database,
   -- and return it as a dict
   SELECT * FROM USERS;
@@ -59,10 +71,10 @@ We can issue SQL queries, like so:
 
     # Or, Sqlite3...
     conn = sqlite3.connect('cool.db')
-    queries = anosql.from_path('queries.sql', 'sqlite3)
+    queries = anosql.from_path('queries.sql', 'sqlite3')
 
     queries.get_all_greetings(conn)
-    # => [(1, 'Hi')]
+    # => [(1, 'en', 'Hi')]
 
     queries.get_all_greetings.__doc__
     # => Get all the greetings in the database
@@ -82,8 +94,8 @@ the ``WHERE`` clause.  You can use parameters to do this:
 
 .. code-block:: sql
 
-  -- name: get-greetings-for-language-and-length
-  -- Get all the greetings in the database
+  -- name: get-greetings-for-language
+  -- Get all the greetings in the database for given language
   SELECT *
   FROM greetings
   WHERE lang = %s;
@@ -93,8 +105,31 @@ And they become positional parameters:
 .. code-block:: python
 
   visitor_language = "en"
-  queries.get_all_greetings(conn, visitor_language)
+  queries.get_greetings_for_language(conn, visitor_language)
+  # => [(1, 'en', 'Hi')]
+
+
+One Row Query
+*************
+
+Often, you would expect at most one row from a query, so that getting a list
+is not convenient. Appending ``?`` to the query name makes it return either one
+tuple if it returned one row, or ``None`` in other cases.
 
+.. code-block:: sql
+
+  -- name: get-a-greeting?
+  -- Get a greeting based on its id
+  SELECT *
+  FROM greetings
+  WHERE id = %s;
+
+Then a tuple is returned:
+
+.. code-block:: python
+
+  queries.get_a_greeting(conn, 1)
+  # => (1, 'en', 'Hi')
 
 
 Named Parameters
@@ -106,7 +141,7 @@ can give the parameters names:
 .. code-block:: sql
 
   -- name: get-greetings-for-language-and-length
-  -- Get all the greetings in the database
+  -- Get all the greetings in the database for given language and length
   SELECT *
   FROM greetings
   WHERE lang = :lang
@@ -122,7 +157,7 @@ parameters:
 
   visitor_language = "en"
 
-  greetings_for_texting = queries.get_all_greetings(
+  greetings_for_texting = queries.get_greetings_for_language_and_length(
                 conn, lang=visitor_language, length_limit=140)
 
 Update/Insert/Delete
@@ -146,9 +181,9 @@ insert query, you can add ``<!`` to the end of your query name.
 Adding custom query loaders.
 ****************************
 
-Out of the box ``anosql`` supports SQLite and PostgreSQL via the stdlib ``sqlite3`` database driver
-and ``psycopg2``. If you would like to extend ``anosql`` to communicate with another type of databases
-you may create a driver adapeter class and register it with ``anosql.register_driver_adapter()``.
+Out of the box, ``anosql`` supports SQLite and PostgreSQL via the stdlib ``sqlite3`` database driver
+and ``psycopg2``. If you would like to extend ``anosql`` to communicate with other types of databases,
+you may create a driver adapter class and register it with ``anosql.core.register_driver_adapter()``.
 
 Driver adapters are duck-typed classes which adhere to the below interface. Looking at ``anosql/adapters`` package
 is a good place to get started by looking at how the ``psycopg2`` and ``sqlite3`` adapters work.
@@ -156,6 +191,7 @@ is a good place to get started by looking at how the ``psycopg2`` and ``sqlite3`
 To register a new loader::
 
     import anosql
+    import anosql.core
 
     class MyDbAdapter():
         def process_sql(self, name, op_type, sql):
@@ -181,7 +217,7 @@ To register a new loader::
             pass
 
 
-    anosql.register_driver_adapter("mydb", MyDbAdapter)
+    anosql.core.register_driver_adapter("mydb", MyDbAdapter)
 
     # To use make a connection to your db, and pass "mydb" as the db_type:
     import mydbdriver
@@ -192,7 +228,7 @@ To register a new loader::
 
     conn.close()
 
-If your adapter constructor takes arguments you can register a function which can build
+If your adapter constructor takes arguments, you can register a function which can build
 your adapter instance::
 
     def adapter_factory():
diff --git a/anosql.egg-info/PKG-INFO b/anosql.egg-info/PKG-INFO
new file mode 100644
index 0000000..1d67dc5
--- /dev/null
+++ b/anosql.egg-info/PKG-INFO
@@ -0,0 +1,267 @@
+Metadata-Version: 2.1
+Name: anosql
+Version: 1.0.2
+Summary: Easy SQL in Python
+Home-page: https://github.com/honza/anosql
+Author: Honza Pokorny
+Author-email: me@honza.ca
+Maintainer: Honza Pokorny
+Maintainer-email: me@honza.ca
+License: UNKNOWN
+Platform: UNKNOWN
+License-File: LICENSE
+
+anosql
+======
+
+**NOTICE**: This project is now deprecated in favor of `aiosql`_.
+
+Unfortunately, I no longer have the time to devote to this project, and aiosql
+is now a lot more popular.  I don't think it makes sense to maintain both.
+Open source ftw!  Thanks for your hard work, `Will`_!
+
+.. _aiosql: https://github.com/nackjicholson/aiosql
+.. _Will: https://github.com/nackjicholson
+
+.. image:: https://badge.fury.io/py/anosql.svg
+    :target: https://badge.fury.io/py/anosql
+    :alt: pypi package version
+
+.. image:: http://readthedocs.org/projects/anosql/badge/?version=latest
+    :target: http://anosql.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
+
+.. image:: https://travis-ci.org/honza/anosql.svg?branch=master
+    :target: https://travis-ci.org/honza/anosql
+    :alt: Travid build status
+
+A Python library for using SQL
+
+Inspired by the excellent `Yesql`_ library by Kris Jenkins.  In my mother
+tongue, *ano* means *yes*.
+
+If you are on python3.6+ or need ``anosql`` to work with ``asyncio``-based database drivers, see the related project, `aiosql <https://github.com/nackjicholson/aiosql>`_.
+
+Complete documentation is available at `Read The Docs <https://anosql.readthedocs.io/en/latest/>`_.
+
+Installation
+------------
+
+::
+
+  $ pip install anosql
+
+Usage
+-----
+
+Basics
+******
+
+Given a ``queries.sql`` file:
+
+.. code-block:: sql
+
+  -- name: get-all-greetings
+  -- Get all the greetings in the database
+  SELECT * FROM greetings;
+
+  -- name: select-users
+  -- Get all the users from the database,
+  -- and return it as a dict
+  SELECT * FROM USERS;
+
+We can issue SQL queries, like so:
+
+.. code-block:: python
+
+    import anosql
+    import psycopg2
+    import sqlite3
+
+    # PostgreSQL
+    conn = psycopg2.connect('...')
+    queries = anosql.from_path('queries.sql', 'psycopg2')
+
+    # Or, Sqlite3...
+    conn = sqlite3.connect('cool.db')
+    queries = anosql.from_path('queries.sql', 'sqlite3')
+
+    queries.get_all_greetings(conn)
+    # => [(1, 'en', 'Hi')]
+
+    queries.get_all_greetings.__doc__
+    # => Get all the greetings in the database
+
+    queries.get_all_greetings.sql
+    # => SELECT * FROM greetings;
+
+    queries.available_queries
+    # => ['get_all_greetings']
+
+
+Parameters
+**********
+
+Often, you want to change parts of the query dynamically, particularly values in
+the ``WHERE`` clause.  You can use parameters to do this:
+
+.. code-block:: sql
+
+  -- name: get-greetings-for-language
+  -- Get all the greetings in the database for given language
+  SELECT *
+  FROM greetings
+  WHERE lang = %s;
+
+And they become positional parameters:
+
+.. code-block:: python
+
+  visitor_language = "en"
+  queries.get_greetings_for_language(conn, visitor_language)
+  # => [(1, 'en', 'Hi')]
+
+
+One Row Query
+*************
+
+Often, you would expect at most one row from a query, so that getting a list
+is not convenient. Appending ``?`` to the query name makes it return either one
+tuple if it returned one row, or ``None`` in other cases.
+
+.. code-block:: sql
+
+  -- name: get-a-greeting?
+  -- Get a greeting based on its id
+  SELECT *
+  FROM greetings
+  WHERE id = %s;
+
+Then a tuple is returned:
+
+.. code-block:: python
+
+  queries.get_a_greeting(conn, 1)
+  # => (1, 'en', 'Hi')
+
+
+Named Parameters
+****************
+
+To make queries with many parameters more understandable and maintainable, you
+can give the parameters names:
+
+.. code-block:: sql
+
+  -- name: get-greetings-for-language-and-length
+  -- Get all the greetings in the database for given language and length
+  SELECT *
+  FROM greetings
+  WHERE lang = :lang
+  AND len(greeting) <= :length_limit;
+
+If you were writing a Postgresql query, you could also format the parameters as
+``%s(lang)`` and ``%s(length_limit)``.
+
+Then, call your queries like you would any Python function with named
+parameters:
+
+.. code-block:: python
+
+  visitor_language = "en"
+
+  greetings_for_texting = queries.get_greetings_for_language_and_length(
+                conn, lang=visitor_language, length_limit=140)
+
+Update/Insert/Delete
+********************
+
+In order to run ``UPDATE``, ``INSERT``, or ``DELETE`` statements, you need to
+add ``!`` to the end of your query name.  Anosql will then execute it properly.
+It will also return the number of affected rows.
+
+Insert queries returning autogenerated values
+*********************************************
+
+If you want the auto-generated primary key to be returned after you run an
+insert query, you can add ``<!`` to the end of your query name.
+
+.. code-block:: sql
+
+  -- name: create-user<!
+  INSERT INTO person (name) VALUES (:name)
+
+Adding custom query loaders.
+****************************
+
+Out of the box, ``anosql`` supports SQLite and PostgreSQL via the stdlib ``sqlite3`` database driver
+and ``psycopg2``. If you would like to extend ``anosql`` to communicate with other types of databases,
+you may create a driver adapter class and register it with ``anosql.core.register_driver_adapter()``.
+
+Driver adapters are duck-typed classes which adhere to the below interface. Looking at ``anosql/adapters`` package
+is a good place to get started by looking at how the ``psycopg2`` and ``sqlite3`` adapters work.
+
+To register a new loader::
+
+    import anosql
+    import anosql.core
+
+    class MyDbAdapter():
+        def process_sql(self, name, op_type, sql):
+            pass
+
+        def select(self, conn, sql, parameters):
+            pass
+
+        @contextmanager
+        def select_cursor(self, conn, sql, parameters):
+            pass
+
+        def insert_update_delete(self, conn, sql, parameters):
+            pass
+
+        def insert_update_delete_many(self, conn, sql, parameters):
+            pass
+
+        def insert_returning(self, conn, sql, parameters):
+            pass
+
+        def execute_script(self, conn, sql):
+            pass
+
+
+    anosql.core.register_driver_adapter("mydb", MyDbAdapter)
+
+    # To use make a connection to your db, and pass "mydb" as the db_type:
+    import mydbdriver
+    conn = mydbriver.connect("...")
+
+    anosql.load_queries("path/to/sql/", "mydb")
+    greetings = anosql.get_greetings(conn)
+
+    conn.close()
+
+If your adapter constructor takes arguments, you can register a function which can build
+your adapter instance::
+
+    def adapter_factory():
+        return MyDbAdapter("foo", 42)
+
+    anosql.register_driver_adapter("mydb", adapter_factory)
+
+Tests
+-----
+
+::
+
+   $ pip install tox
+   $ tox
+
+License
+-------
+
+BSD, short and sweet
+
+.. _Yesql: https://github.com/krisajenkins/yesql/
+
+
diff --git a/anosql.egg-info/SOURCES.txt b/anosql.egg-info/SOURCES.txt
new file mode 100644
index 0000000..0f57b22
--- /dev/null
+++ b/anosql.egg-info/SOURCES.txt
@@ -0,0 +1,46 @@
+CHANGELOG
+LICENSE
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+test_requirements.txt
+tox.ini
+anosql/__init__.py
+anosql/core.py
+anosql/exceptions.py
+anosql/patterns.py
+anosql.egg-info/PKG-INFO
+anosql.egg-info/SOURCES.txt
+anosql.egg-info/dependency_links.txt
+anosql.egg-info/top_level.txt
+anosql/adapters/__init__.py
+anosql/adapters/psycopg2.py
+anosql/adapters/sqlite3.py
+docs/Makefile
+docs/conf.py
+docs/defining_queries.rst
+docs/extending.rst
+docs/getting_started.rst
+docs/index.rst
+docs/make.bat
+docs/upgrading.rst
+docs/source/anosql.adapters.psycopg2.rst
+docs/source/anosql.adapters.rst
+docs/source/anosql.adapters.sqlite3.rst
+docs/source/anosql.core.rst
+docs/source/anosql.exceptions.rst
+docs/source/anosql.patterns.rst
+docs/source/anosql.rst
+docs/source/modules.rst
+tests/__init__.py
+tests/conftest.py
+tests/test_psycopg2.py
+tests/test_simple.py
+tests/test_sqlite3.py
+tests/blogdb/data/blogs_data.csv
+tests/blogdb/data/users_data.csv
+tests/blogdb/sql/blogs/blogs.sql
+tests/blogdb/sql/blogs/blogs_pg.sql
+tests/blogdb/sql/blogs/blogs_sqlite.sql
+tests/blogdb/sql/users/users.sql
\ No newline at end of file
diff --git a/anosql.egg-info/dependency_links.txt b/anosql.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/anosql.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/anosql.egg-info/top_level.txt b/anosql.egg-info/top_level.txt
new file mode 100644
index 0000000..afbaa5e
--- /dev/null
+++ b/anosql.egg-info/top_level.txt
@@ -0,0 +1,2 @@
+anosql
+tests
diff --git a/anosql/__init__.py b/anosql/__init__.py
index 1da6fd6..6d24ca7 100644
--- a/anosql/__init__.py
+++ b/anosql/__init__.py
@@ -1,5 +1,4 @@
-from anosql.core import from_path, from_str, SQLOperationType
-from anosql.exceptions import SQLLoadException, SQLParseException
+from .core import from_path, from_str, SQLOperationType
+from .exceptions import SQLLoadException, SQLParseException
 
 __all__ = ["from_path", "from_str", "SQLOperationType", "SQLLoadException", "SQLParseException"]
-
diff --git a/anosql/adapters/psycopg2.py b/anosql/adapters/psycopg2.py
index da2fcc2..28346e0 100644
--- a/anosql/adapters/psycopg2.py
+++ b/anosql/adapters/psycopg2.py
@@ -1,6 +1,6 @@
 from contextlib import contextmanager
 
-from anosql.patterns import var_pattern
+from ..patterns import var_pattern
 
 
 def replacer(match):
@@ -41,9 +41,9 @@ class PsycoPG2Adapter(object):
             cur.execute(sql, parameters)
 
     @staticmethod
-    def insert_update_delete_many(conn, _query_name, sql, parmeters):
+    def insert_update_delete_many(conn, _query_name, sql, parameters):
         with conn.cursor() as cur:
-            cur.executemany(sql, parmeters)
+            cur.executemany(sql, parameters)
 
     @staticmethod
     def insert_returning(conn, _query_name, sql, parameters):
diff --git a/anosql/core.py b/anosql/core.py
index 5cee44d..954eda8 100644
--- a/anosql/core.py
+++ b/anosql/core.py
@@ -1,9 +1,9 @@
 import os
 
-from anosql.adapters.psycopg2 import PsycoPG2Adapter
-from anosql.adapters.sqlite3 import SQLite3DriverAdapter
-from anosql.exceptions import SQLLoadException, SQLParseException
-from anosql.patterns import (
+from .adapters.psycopg2 import PsycoPG2Adapter
+from .adapters.sqlite3 import SQLite3DriverAdapter
+from .exceptions import SQLLoadException, SQLParseException
+from .patterns import (
     query_name_definition_pattern,
     empty_pattern,
     doc_comment_pattern,
@@ -96,6 +96,7 @@ class SQLOperationType(object):
     INSERT_UPDATE_DELETE_MANY = 2
     SCRIPT = 3
     SELECT = 4
+    SELECT_ONE_ROW = 5
 
 
 class Queries:
@@ -172,6 +173,9 @@ def _create_fns(query_name, docs, op_type, sql, driver_adapter):
             return driver_adapter.insert_update_delete_many(conn, query_name, sql, *parameters)
         elif op_type == SQLOperationType.SCRIPT:
             return driver_adapter.execute_script(conn, sql)
+        elif op_type == SQLOperationType.SELECT_ONE_ROW:
+            res = driver_adapter.select(conn, query_name, sql, parameters)
+            return res[0] if len(res) == 1 else None
         elif op_type == SQLOperationType.SELECT:
             return driver_adapter.select(conn, query_name, sql, parameters)
         else:
@@ -213,6 +217,9 @@ def load_methods(sql_text, driver_adapter):
     elif query_name.endswith("#"):
         op_type = SQLOperationType.SCRIPT
         query_name = query_name[:-1]
+    elif query_name.endswith("?"):
+        op_type = SQLOperationType.SELECT_ONE_ROW
+        query_name = query_name[:-1]
     else:
         op_type = SQLOperationType.SELECT
 
diff --git a/anosql/patterns.py b/anosql/patterns.py
index a81d4ca..0b8bedf 100644
--- a/anosql/patterns.py
+++ b/anosql/patterns.py
@@ -23,7 +23,7 @@ Pattern: Identifies SQL comments.
 var_pattern = re.compile(
     r'(?P<dblquote>"[^"]+")|'
     r"(?P<quote>\'[^\']+\')|"
-    r"(?P<lead>[^:]):(?P<var_name>[\w-]+)(?P<trail>[^:])"
+    r"(?P<lead>[^:]):(?P<var_name>[\w-]+)(?P<trail>[^:]?)"
 )
 """
 Pattern: Identifies variable definitions in SQL code.
diff --git a/docs/conf.py b/docs/conf.py
index 5e76ead..1109268 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -19,6 +19,7 @@
 # import os
 # import sys
 # sys.path.insert(0, os.path.abspath('.'))
+import pkg_resources
 
 # -- General configuration ------------------------------------------------
 
@@ -57,9 +58,9 @@ author = u'Honza Pokorny'
 # built documents.
 #
 # The short X.Y version.
-version = u'1.0.0'
+version = pkg_resources.get_distribution('anosql').version
 # The full version, including alpha/beta/rc tags.
-release = u'1.0.0'
+release = version
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -153,7 +154,7 @@ html_theme = 'alabaster'
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = []
 
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
diff --git a/docs/defining_queries.rst b/docs/defining_queries.rst
index ef968f7..20b456c 100644
--- a/docs/defining_queries.rst
+++ b/docs/defining_queries.rst
@@ -6,9 +6,9 @@ Query Names & Comments
 ======================
 
 Name definitions are how ``anosql`` determines how to name the SQL code blocks which are loaded.
-A query name definition is a normal SQL comment starting with "-- name:" and is followed by the
-name of the query. You can use ``-`` or ``_`` in your query names, but the methods in python
-will always be valid python names using underscores.
+A query name definition is a normal SQL comment starting with "\-\- name:" and is followed by the
+name of the query. You can use ``-`` or ``_`` in your query names, but the methods in Python
+will always be valid Python names using underscores.
 
 .. code-block:: sql
 
@@ -18,7 +18,7 @@ will always be valid python names using underscores.
 The above example when loaded by ``anosql.from_path`` will return an object with a
 ``.get_all_blogs(conn)`` method.
 
-Your SQL comments will be added to your methods as python documentation, and accessible by calling
+Your SQL comments will be added to your methods as Python docstrings, and accessible by calling
 ``help()`` on them.
 
 .. code-block:: sql
@@ -33,7 +33,7 @@ Your SQL comments will be added to your methods as python documentation, and acc
     queries = anosql.from_path("blogs.sql", "sqlite3")
     help(anosql.get_all_blogs)
 
-output
+returns
 
 .. code-block:: text
 
@@ -52,7 +52,7 @@ execute and return results. In the above section the ``get-all-blogs`` name has
 characters trailing it. This lack of operator is actually the most basic operator which performs
 SQL ``select`` statements and returns a list of rows. When writing an application you will often
 need to perform other operations besides selects, like inserts, deletes, and bulk opearations. The
-operators detailed in this section let you declare in your SQL, how your code should be executed
+operators detailed in this section let you declare in your SQL how your code should be executed
 by the database driver.
 
 Insert/Update/Delete with ``!``
@@ -142,7 +142,7 @@ many blog rows.
         :published
     )
 
-Applying this to a list of blogs in python::
+Applying this to a list of blogs in Python::
 
     queries = anosql.from_path("blogs.sql", "psycopg2")
     blogs = [
@@ -155,8 +155,8 @@ Applying this to a list of blogs in python::
 Execute SQL script statements with ``#``
 ---------------------------------------------
 
-Executes some sql statements as a script. These methods don't do variable substitution, or return
-any rows. An example usecase is using data definition statements like create table in order to
+Executes some SQL statements as a script. These methods don't do variable substitution, or return
+any rows. An example use case is using data definition statements like `create` table in order to
 setup your database.
 
 .. code-block:: sql
diff --git a/docs/extending.rst b/docs/extending.rst
index dc25c94..a2f4ec8 100644
--- a/docs/extending.rst
+++ b/docs/extending.rst
@@ -4,10 +4,12 @@
 Extending anosql
 ################
 
+.. _driver-adapters:
+
 Driver Adapters
 ---------------
 
-Database driver adapters in ``anosql`` are a duck-typed class which follow the below interface.::
+Database driver adapters in ``anosql`` are duck-typed classes which follow the below interface.::
 
     class MyDbAdapter():
         def process_sql(self, name, op_type, sql):
@@ -33,7 +35,7 @@ Database driver adapters in ``anosql`` are a duck-typed class which follow the b
             pass
 
 
-    anosql.register_driver_adapter("mydb", MyDbAdapter)
+    anosql.core.register_driver_adapter("mydb", MyDbAdapter)
 
 If your adapter constructor takes arguments you can register a function which can build
 your adapter instance::
@@ -41,7 +43,7 @@ your adapter instance::
     def adapter_factory():
         return MyDbAdapter("foo", 42)
 
-    anosql.register_driver_adapter("mydb", adapter_factory)
+    anosql.core.register_driver_adapter("mydb", adapter_factory)
 
 Looking at the source of the builtin
 `adapters/ <https://github.com/honza/anosql/tree/master/anosql/adapters>`_ is a great place
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index f0537bb..6385497 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -24,7 +24,7 @@ Each method on an ``anosql.Queries`` object accepts a database connection to use
       from worlds
      where world_name = :world_name;
 
-By specifying ``db_driver="sqlite3"`` we can use the python stdlib ``sqlite3`` driver to execute these sql queries and
+By specifying ``db_driver="sqlite3"`` we can use the Python stdlib ``sqlite3`` driver to execute these SQL queries and
 get the results. We're also using the ``sqlite3.Row`` type for our records to make it easy to access our data via
 their column names rather than as tuple indices.
 
diff --git a/docs/index.rst b/docs/index.rst
index b6fc0f7..45f80f0 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -8,20 +8,22 @@ Welcome to anosql's documentation!
 
 .. image:: https://badge.fury.io/py/anosql.svg
     :target: https://badge.fury.io/py/anosql
+    :alt: pypi package version
 
 .. image:: http://readthedocs.org/projects/anosql/badge/?version=latest
     :target: http://anosql.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation status
 
 .. image:: https://travis-ci.org/honza/anosql.svg?branch=master
     :target: https://travis-ci.org/honza/anosql
+    :alt: Travis build status
 
 A Python library for using SQL
 
 Inspired by the excellent `Yesql`_ library by Kris Jenkins.  In my mother
 tongue, *ano* means *yes*.
 
-If you are on python3.6+ or need ``anosql`` to work with ``asyncio`` based database drivers.
-See the related project `aiosql <https://github.com/nackjicholson/aiosql>`_.
+If you are on python3.6+ or need ``anosql`` to work with ``asyncio`` based database drivers, see the related project `aiosql <https://github.com/nackjicholson/aiosql>`_.
 
 Installation
 ------------
@@ -58,7 +60,7 @@ We can issue SQL queries, like so:
 
     # Or, Sqlite3...
     conn = sqlite3.connect('cool.db')
-    queries = anosql.from_path('queries.sql', 'sqlite3)
+    queries = anosql.from_path('queries.sql', 'sqlite3')
 
     queries.get_all_greetings(conn)
     # => [(1, 'Hi')]
@@ -76,13 +78,13 @@ We can issue SQL queries, like so:
 Parameters
 **********
 
-Often, you want to change parts of the query dynamically, particularly values in the WHERE clause.
+Often, you want to change parts of the query dynamically, particularly values in the ``WHERE`` clause.
 You can use parameters to do this:
 
 .. code-block:: sql
 
-  -- name: get-greetings-for-language-and-length
-  -- Get all the greetings in the database
+  -- name: get-greetings-for-language
+  -- Get all the greetings in the database for a given language
   SELECT *
   FROM greetings
   WHERE lang = %s;
@@ -92,7 +94,7 @@ And they become positional parameters:
 .. code-block:: python
 
   visitor_language = "en"
-  queries.get_all_greetings(conn, visitor_language)
+  queries.get_all_greetings_for_language(conn, visitor_language)
 
 
 
@@ -103,8 +105,8 @@ To make queries with many parameters more understandable and maintainable, you c
 
 .. code-block:: sql
 
-  -- name: get-greetings-for-language-and-length
-  -- Get all the greetings in the database
+  -- name: get-greetings-for-language
+  -- Get all the greetings in the database for given language and length
   SELECT *
   FROM greetings
   WHERE lang = :lang
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..adf5ed7
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,7 @@
+[bdist_wheel]
+universal = 1
+
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/setup.py b/setup.py
index 6d82a4d..5031b8e 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ with open('README.rst') as readme_file:
 
 setup(
     name='anosql',
-    version='1.0.1',
+    version='1.0.2',
     url='https://github.com/honza/anosql',
     install_requires=[],
     description='Easy SQL in Python',
diff --git a/tests/blogdb/sql/users/users.sql b/tests/blogdb/sql/users/users.sql
index c426c91..548f5c0 100644
--- a/tests/blogdb/sql/users/users.sql
+++ b/tests/blogdb/sql/users/users.sql
@@ -5,3 +5,7 @@ select * from users;
 -- name: get-all-sorted
 -- Get all user records sorted by username
 select * from users order by username asc;
+
+-- name: get-one?
+-- Get one user based on its id
+select username, firstname, lastname from users where userid = %s;
diff --git a/tests/conftest.py b/tests/conftest.py
index 842bdf3..b883854 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -20,7 +20,7 @@ def populate_sqlite3_db(db_path):
                 firstname integer not null,
                 lastname text not null
             );
-            
+
             create table blogs (
                 blogid integer not null primary key,
                 userid integer not null,
diff --git a/tests/test_simple.py b/tests/test_simple.py
index 9f43996..89a0ad8 100644
--- a/tests/test_simple.py
+++ b/tests/test_simple.py
@@ -74,6 +74,16 @@ def test_parametrized_insert_named(sqlite):
     assert q.get_all_values(sqlite) == [(10, 11, 12)]
 
 
+def test_one_row(sqlite):
+    _test_one_row = ("-- name: one-row?\n"
+                     "SELECT 1, 'hello';\n\n"
+                     "-- name: two-rows?\n"
+                     "SELECT 1 UNION SELECT 2;\n")
+    q = anosql.from_str(_test_one_row, "sqlite3")
+    assert q.one_row(sqlite) == (1, 'hello')
+    assert q.two_rows(sqlite) is None
+
+
 def test_simple_query_pg(postgresql):
     _queries = ("-- name: create-some-table#\n"
                 "-- testing insertion\n"
@@ -193,3 +203,13 @@ def test_parameterized_select_named_pg(postgresql):
     q.insert_some_value(postgresql)
 
     assert q.get_all_values(postgresql, a=1) == [(1, 2, 3)]
+
+
+def test_without_trailing_semi_colon_pg():
+    """Make sure keywords ending queries are recognized even without
+    semi-colons.
+    """
+    _queries = ("-- name: get-by-a\n"
+                "SELECT a, b, c FROM foo WHERE a = :a\n")
+    q = anosql.from_str(_queries, "psycopg2")
+    assert q.get_by_a.sql == "SELECT a, b, c FROM foo WHERE a = %(a)s"
diff --git a/tox.ini b/tox.ini
index 7af2b1c..d584645 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,27 @@
 [tox]
-envlist = py27, py35
+envlist = py27, py35, py37, flake8, docs, check-manifest
 skip_missing_interpreters = True
 
 [testenv]
 deps = -rtest_requirements.txt
-commands = py.test tests
+commands = {envpython} -m pytest {posargs:tests}
+
+[testenv:flake8]
+skip_install = true
+deps = flake8
+commands = {envpython} -m flake8 {posargs}
+
+[flake8]
+max-line-length=100
+
+[testenv:docs]
+deps =
+  sphinx
+  alabaster
+commands = {envpython} -m sphinx.cmd.build -W -b html docs docs/_build/html
+
+[testenv:check-manifest]
+skip_install = true
+deps =
+  check-manifest
+commands = {envpython} -m check_manifest