Skip to content

Commit

Permalink
Merge pull request #1 from LabKey/experiment
Browse files Browse the repository at this point in the history
Introduce _netrc, experiment api, and support for python 2 & 3
  • Loading branch information
labkey-nicka committed Nov 11, 2015
2 parents eef7719 + 7b95563 commit 313a6c0
Show file tree
Hide file tree
Showing 14 changed files with 1,733 additions and 589 deletions.
87 changes: 72 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# About
Python client API for LabKey Server. To get started, please see the [full documentation for this library](https://www.labkey.org/wiki/home/Documentation/page.view?name=python).
The Python client API for LabKey Server lets you query, insert and update data on a LabKey Server from a Python client.

# Release Notes

Changes in the current release:

- Support for Python 3
- Support for netrc files (.labkeycredentials.txt files are now deprecated)
- New methods for working with assay data:
- [load_batch](https://github.com/LabKey/labkey-api-python/tree/master/labkey/experment.py)
- [save_batch](https://github.com/LabKey/labkey-api-python/tree/master/labkey/experment.py)
- server_context parameter added to all methods
- PEP standards - the latest version follows PEP code styling standards
- New [samples](https://github.com/LabKey/labkey-api-python/tree/master/samples)

# Installation
To install, simply use `pip`:
Expand All @@ -9,27 +22,71 @@ $ pip install labkey
```

# Credentials
In order to the use the Python client API for LabKey Server, you will need to specify your login credentials in a credential file. The package assumes that this file will be located either:
As of v0.4.0 this API no longer supports using a ``.labkeycredentials.txt`` file, and now uses the .netrc files similar to the other labkey APIs. Additional .netrc [setup instructions](https://www.labkey.org/wiki/home/Documentation/page.view?name=netrc) can be found at the link.

## Set Up a netrc File

On a Mac, UNIX, or Linux system the netrc file should be named ``.netrc`` (dot netrc) and on Windows it should be named ``_netrc`` (underscore netrc). The file should be located in your home directory and the permissions on the file must be set so that you are the only user who can read it, i.e. it is unreadable to everyone else.

1. ``$HOME/.labkeycredentials.txt``
2. The location will be specified in the ``LABKEY_CREDENTIALS`` environment variable.
To create the netrc on a Windows machine, first create an environment variable called ’HOME’ that is set to your home directory (for example, C:/Users/johndoe) or any directory you want to use.

In that directory, create a text file with the prefix appropriate to your system, either an underscore or dot.

The following three lines must be included in the file. The lines must be separated by either white space (spaces, tabs, or newlines) or commas:
```
machine <remote-instance-of-labkey-server>
login <user-email>
password <user-password>
```

The ``labkeycredentials`` file must be in the following format. (3 separate lines):
For example:
```
machine https://hosted.labkey.com
login labkeypython@gmail.com
password python
machine mymachine.labkey.org
login user@labkey.org
password mypassword
```
where:
- machine: URL of your LabKey Server
- login: email address to be used to login to the LabKey Server
- password: password associated with the login
Note that the netrc file only deals with connections at the machine level and should not include a port or protocol designation, meaning both "mymachine.labkey.org:8888" and "https://mymachine.labkey.org" are incorrect.

A sample ``labkeycredentials`` file has been shipped with the source and named ``.labkeycredentials.sample``.
# Supported Functions

- **labkey.query.select_rows()** - Query and get results sets from LabKey Server.
- **labkey.query.execute_sql()** - Execute SQL (LabKey SQL dialect) through the query module on LabKey Server.
- **labkey.query.insert_rows()** - Insert rows into a table on LabKey Server.
- **labkey.query.update_rows()** - Update rows in a table on LabKey Server.
- **labkey.query.delete_rows()** - Delete records in a table on LabKey Server.
- **labkey.experiment.load_batch()** - Retreive assay data (batch level) from LabKey Server.
- **labkey.experiment.save_batch()** - Save assay data (batch level) on LabKey Server.

# Examples

Sample code is available in the [samples](https://github.com/LabKey/labkey-api-python/tree/experiment/samples) directory.

The following gets data from the Users table on your local machine:

```python
from labkey.utils import create_server_context
from labkey.query import select_rows

print("Create a server context")
labkey_server = 'localhost:8080'
project_name = 'ModuleAssayTest' # Project folder name
contextPath = 'labkey'
schema = 'core'
table = 'Users'

server_context = create_server_context(labkey_server, project_name, contextPath, use_ssl=False)

result = select_rows(server_context, schema, table)
if result is not None:
print(result['rows'][0])
print("select_rows: Number of rows returned: " + str(result['rowCount']))
else:
print('select_rows: Failed to load results from ' + schema + '.' + table)
```

# Supported Versions
Python 2.6 or 2.7 are fully supported.
LabKey Server v11.1 and later.
Python 2.6+ and 3.4+ are fully supported.
LabKey Server v13.3 and later.

# Contributing
This library and the LabKey Server are maintained by the LabKey Software Foundation. If you have any questions or need support, please use the [LabKey Server support forum](https://www.labkey.org/wiki/home/page.view?name=support).
11 changes: 6 additions & 5 deletions labkey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
__title__ = 'labkey'
__version__ = '0.3.0'
__author__ = 'LabKey Software'
__license__ = 'Apache 2.0'
from labkey import query, experiment, utils # wiki, messageboard
from pkg_resources import get_distribution

from labkey import query, wiki, messageboard
__title__ = get_distribution('labkey').project_name
__version__ = get_distribution('labkey').version
__author__ = 'LabKey Software'
__license__ = 'Apache License 2.0'
68 changes: 68 additions & 0 deletions labkey/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#
# Copyright (c) 2015 LabKey Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from requests import exceptions


# base exception class for server responses
class RequestError(exceptions.HTTPError):
default_msg = 'Server Error'

def __init__(self, server_response=None):
if server_response is not None:
try:
decoded = server_response.json()
if 'exception' in decoded:
# use labkey server error message if available
msg = decoded['exception']
self.server_exception = decoded
else:
msg = self.default_msg
except ValueError:
# no valid json to decode
raise ServerNotFoundError(server_response)

self.message = '{0}: {1}'.format(server_response.status_code, msg)

self.response = server_response


class QueryNotFoundError(RequestError):
default_msg = 'Query Resource Not Found'


class RequestAuthorizationError(RequestError):
default_msg = 'Authorization Failed'


class ServerNotFoundError(RequestError):
SERVER_NOT_FOUND_MSG = 'Server resource not found. Please verify context path and project path are valid'

def __init__(self, server_response=None):
self.message = '{0}: {1}'.format(server_response.status_code, self.SERVER_NOT_FOUND_MSG)
self.response = server_response


class ServerContextError(exceptions.HTTPError):
def __init__(self, inner_exception=None):
self.message = self._get_message(inner_exception)
self.exception = inner_exception

def _get_message(self, e):
switcher = {
exceptions.SSLError:
'Failed to match server SSL configuration. Ensure the server_context is configured correctly.'
}
return switcher.get(type(e), 'Please verify server_context is configured correctly')
Loading

0 comments on commit 313a6c0

Please sign in to comment.