A Python client for interacting with Knack applications.
Please @ me (johnclary, repo maintainer) in your issue description.
Contributions are welcome. Know that your contributions are donated to the public domain.
Knackpy requires Python v3.6+.
pip install knackpy
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey',
tzinfo="US/Central" # Be careful, this is the default value!
)
>>> kn.data
[{'store_id': 30424, 'inspection_date': 1479448800000, 'id': '58598262bcb3437b51194040'},...]
- Object and view-based requests
- Filters
- Parsing of fieldnames and field labels
- Create, update, and delete records
- CSV output
- File downloads
- Page and Row Limitng
- Localization and Timezone Settings
- Connection Fields
- Timeouts and Retrying
- Knack Record ID's
Get data from a Knack view.
>>> from knackpy import Knack
>>> kn = Knack(
scene='scene_34',
view='view_10',
app_id='abc123'
)
>>> kn.data_raw
[{'field_1': 30424, 'field_1_raw': 30424, 'field_2': '11/18/2016'},...]
Provide a list of the view's reference objects to return humanized field names.
>>> kn = Knack(
scene='scene_34',
view='view_10',
ref_obj=['object_1', 'object_2'],
app_id='myappid',
api_key='topsecretapikey'
)
>>> kn.data
[{'store_id': 30424, 'inspection_date': 1479448800000, 'id': '58598262bcb3437b51194040'},...]
Retrieve data directly from an object.
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey'
)
>>> kn.data
[{'store_id': 30424, 'inspection_date': 1479448800000, 'id': '58598262bcb3437b51194040'},...]
You can pass a filter to object-based requests.
>>> filters = {
'match': 'and',
'rules': [
{
'field':'field_10',
'operator':'is',
'value':'No'
},
{
'field':'field_11',
'operator':'is',
'value':'Yes'
}
]
}
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey',
filters=filters
)
Field metadata is available in object-based requests or in view-based requests when reference objects have been specified.
>>> kn.fields
{'field_1': {' ': 'store_id', 'key': 'field_1,required': False, 'type': 'auto_increment'},...}
>>> kn.fieldnames
['store_id', 'inspection_date', 'store_status',...]
>>> kn.field_map
{'store_id' : 'field_1', 'store_status' : 'field_2',...}
You can download files for the records you retrieve from a view. Files are overwritten by default:
>>> kn.download(overwrite=False) # Writes all new files to `_downloads` directory
>>> kn.download(
destination="my_downloads", # Writes to `my_downloads` directory
label_fields=["Attachment ID", "Date"], # Prepends the "Attachment ID" and "Date" values to the filename
download_fields=["Photo", "Document"] # Downloads files from these specific fields only
)
You can write Knack data to a CSV
file. Note that timestamps are converted to ISO 8601 format when written to CSV.
>>> kn.to_csv('data.csv')
"store_id","inspection_date","store_status"
"30424","2020-01-05T15:05:00-05:00","OPEN"
"30200","2020-01-05T15:05:00-05:00","CLOSED"
...
Create a new record.
>>> import knackpy
>>> record = {'field_1': 30424}
>>> response = knackpy.record(
record,
obj_key='object_12',
api_id='myappid',
api_key='topsecretapikey',
method='create'
)
{ 'id':'6a204bd89f3c8348afd5c77c717a097a', 'field_1': 30424, ...}
Update a record.
>>> import knackpy
>>> record = {'id':'6a204bd89f3c8348afd5c77c717a097a','field_1': 2049}
>>> response = knackpy.record(
record,
obj_key='object_12',
app_id='myappid',
api_key='topsecretapikey',
method='update'
)
{ 'id':'6a204bd89f3c8348afd5c77c717a097a', 'field_1': 2049, ...}
Delete a record
>>> record = {'id':'6a204bd89f3c8348afd5c77c717a097a'}
>>> response = knackpy.record(
record,
obj_key='object_12',
app_id='myappid',
api_key='topsecretapikey',
method='delete'
)
# API returns `{'delete': True}`
Get an app's configuration data (objects, scenes, etc.)
>>> from knackpy import get_app_data
>>> my_app = get_app_data('myAppIdString')
>>> my_app['name']
"John's Amazing App"
Use rows_per_page
(default=1000
) and/or page_limit
(default=1000
) to limit results.
Note that maximum rows-per-page allowed by the Knack API is 1000.
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey',
rows_per_page=1, #
page_limit=1
)
Note that knackpy's default timezone value is US/Central
.
You may be wondering why timezone settings are concern, given that Knackpy, like the Knack API, returns timestamp values as Unix timestamps in millesconds (thus, there is no timezone encoding at all). However, the Knack API confusingly returns millisecond timestamps in your localized timezone!
For example, if you inspect a timezone value in Knack, e.g., 1578254700000
, this value represents Sunday, January 5, 2020 8:05:00 PM local time.
To address this, knackpy handles the conversion of Knack timestamps into real millisecond unix timestamps which are timezone naive. However, the original "local timestamps" are preserved in the Knack.data_raw
object. If you're working with that data, you'll need to convert the tiemstamps yourself. See the Knack._convert_timestamps
method in the source code for help.
Use the tzinfo
parameter to specify your applications timezone setting. This value should be formatted as a timezone string compliant to the tz database.
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey',
tzinfo="US/Central" # Be careful, this is the default value!
)
By default, knackpy will attempt to send an HTTP request to the Knack API 5 times until a status code of 200
is returned. You can adjust the number of request attempts (max_attempts
, default=5
) and the timeout (timeout
, default=10
):
>>> kn = Knack(
obj='object_1',
app_id='abc123',
api_key='topsecretapikey',
max_attempts=4,
timeout=20,
tzinfo="US/Central" # Be careful, this is the default value!
)
By default, connection fields are (if one connection) returned as the field's display name, or (if many connetions) an array of the connection fields' display names.
Use raw_connections=True
to retain the entire connection array from Knack:
[
{
"id": "5a7a027b82fecf67ab01f263", # Record ID of connected record
"identifier": "Pizza Hut" # This the value of the connection's display name field
}
],
By default, the Knack record ID is included within each record under the id
key. This can create problems if you have a field named id
in our object. You can exclude the record IDs entirely with include_ids=False
or set your own ID key with id_key="your_field_id"
.
As a work of the City of Austin, this project is in the public domain within the United States.
Additionally, we waive copyright and related rights of the work worldwide through the CC0 1.0 Universal public domain dedication.