spaceandtime


Namespaceandtime JSON
Version 1.1.25 PyPI version JSON
download
home_pageNone
SummarySDK for Space and Time verifiable database
upload_time2024-05-18 23:13:50
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT License Copyright (c) 2023 Space and Time Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords space and time sxt spaceandtime verifiable database web3 blockchain data warehouse data
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
  
  

## Python Space and Time SDK 

  

Python SDK for Space and Time Gateway (python version >= 3.11)

  

## Installation Instructions

  

_Note: The recommended approach to storing keys is using an `.env` file. 
For more information, please see: https://docs.spaceandtime.io/docs/dotenv_

  

```sh
pip install spaceandtime
```

 
  

### Getting Started

```python
# Initializing the Space and Time usage.
from spaceandtime import SpaceAndTime

sxt = SpaceAndTime()
sxt.authenticate()

success, rows = sxt.execute_query(
	'select * from POLYGON.BLOCKS limit 5')
print( rows )
```

The authentication without arguments will seek out a default `.env` file and use credentials found there.  It also supports passing in a specific ```filepath.env``` or simply supplying ```user_id``` and ```private_key```.

The generated ``access_token`` is valid for 25 minutes and the ``refresh_token`` for 30 minutes.

There are a number of convenience features in the SDK for handling return data sets. By default, data sets are returned as a list-of-dictionaries, however can be easily turned into other formats, such as CSV.

```python
# use triple-quotes to insert more complicated sql:
success, rows = sxt.execute_query("""
	SELECT 
	substr(time_stamp,1,7) AS YrMth
	,count(*) AS block_count
	FROM polygon.blocks 
	GROUP BY YrMth
	ORDER BY 1 desc """ )

# print results as CSV
print( sxt.json_to_csv(rows) )
```

More data transforms will be added over time.

### SXTUser Object

All SQL requests are handled by an authenticated user object.  The ```sxt``` wrapper object contains a 'default user' object for simplicity, managing and authenticating as needed.  It is however exposed if needed:

```python
print( sxt.user )
```

You can also manage users directly.  This allows you to load and authenticate multiple users at a time, in case your application needs to manage several accounts.

_**All interaction with the network requires an authenticated user.**_

The user object owns the authenticated connection to the network, so all requests are submitted by a user object.

```python
# Multiple Users
from spaceandtime import SXTUser

suzy = SXTUser('./users/suzy.env', authenticate=True)

bill = SXTUser()
bill.load()         # defaults to "./.env"
bill.authenticate()

# new user
pat = SXTUser(user_id='pat')
pat.new_keypair()
pat.api_url = suzy.api_url
pat.save() # <-- Important! don't lose keys!
pat.authenticate()
```

There is also some capability to administer your subscription using the SDK.  This capability will expand more over time.

```python
# suzy invites pat to her subcription:
if suzy.user_type in ['owner','admin']: 
	joincode = suzy.generate_joincode()
	success, results = pat.join_subscription(joincode)
	print( results )
```



### DISCOVERY

There are several discovery functions that allow insight to the Space and Time network metadata.


```python
# discovery calls provide network information
success, schemas = sxt.discovery_get_schemas()

print(f'There are {len(schemas)} schemas currently on the network.')
print(schemas)
```


### Creating Tables

The SDK abstracts away complexity from making a new table into a Table object.  This object contains all needed components to be self-sufficient _EXCEPT_ for an authenticated user object, which is required to submit the table creation to the network.

```python
# Create a table
from spaceandtime import SXTTable, SXTTableAccessType

tableA = SXTTable(name = "SXTTEMP.MyTestTable", 
				new_keypair = True, 
				default_user = sxt.user,
				logger = sxt.logger,
				access_type = SXTTableAccessType.PERMISSSIONED)

tableA.create_ddl = """
	CREATE TABLE {table_name} 
	( MyID         int
	, MyName       varchar
	, MyDate       date
	, Primary Key(MyID) 
	) {with_statement}
""" 

# create new biscuits for your table
tableA.add_biscuit('read',  tableA.PERMISSION.SELECT )

tableA.add_biscuit('write', tableA.PERMISSION.SELECT, 
							tableA.PERMISSION.INSERT, 
							tableA.PERMISSION.UPDATE, 
							tableA.PERMISSION.DELETE,
							tableA.PERMISSION.MERGE )

tableA.add_biscuit('admin', tableA.PERMISSION.ALL )

tableA.save() # <-- Important!  Don't lose your keys!

# create with assigned default user
success, results = tableA.create()  
```


The ```table.create_ddl``` and ```table.with_statement``` property will substitute {names} to replace with class values.  In the example above, the ```{table_name}``` will be replace with ```tableA.table_name``` and the ```{with_statement}``` will be replaced with a valid WITH statement, itself with substitutions for ```{public_key}``` and ```{access_type}```.

Note, if the ```{with_statement}``` placeholder is absent, the table object will attempt to add dynamically.

When adding biscuits, they can either be added as string tokens, or as SXTBiscuit type objects, or as a list of either.

The ```tableA.save()``` function will save all keys, biscuits, and table attributes to a shell-friendly format, such that you could execute the file in shell and load all values to environment variables, for use in other scripting. For example,

```sh
Stephen~$ . ./table--SXTTEMP.New_TableName.sql
Stephen~$ echo $TABLE_NAME
  SXTTEMP.New_TableName
```
This allows table files created in the python SDK to be used with the SxT CLI. 


### Insert, Deletes, and Selects

There are helper functions to assist quickly adding, removing, and selecting data in the table.  Note, these are just helper functions for the specific table object - for more general SQL interface, use the ```sxt.execute_query()``` function. 

```python
from pprint import pprint # for better viewing of data

# generate some dummy data
data = [{'MyID':i, 'MyName':chr(64+i), 'MyDate':f'2023-09-0{i}'} for i in list(range(1,10))]

# insert into the table
tableA.insert.with_list_of_dicts(data)

# select out again, just for fun
success, rows = tableA.select()
pprint( rows )

tableA.delete(where='MyID=6')

# one less than last time
success, rows = tableA.select()
pprint( rows )
```

### Creating Views 

The SXTView object inherits from the same base class as SXTTable, so the two are very similar.  One notable difference is a view's need for a biscuit for each table referenced.  To add clarity and remind of this requirement, a view contains a ```table_biscuit``` property. Also note that views don't need DML PERMISSIONS, like insert or delete.

```python
# create a view 
from spaceandtime import SXTView

viewB = SXTView('SXTTEMP.MyTest_Odds',
 				default_user=tableA.user, 
				private_key=tableA.private_key, 
				logger=tableA.logger)

viewB.add_biscuit('read', viewB.PERMISSION.SELECT)
viewB.add_biscuit('admin', viewB.PERMISSION.ALL) 
viewB.table_biscuit = tableA.get_biscuit('admin')

viewB.create_ddl = """
	CREATE VIEW {view_name} 
	{with_statement} 
	AS
	SELECT *
	FROM """ + tableA.table_name + """
	WHERE MyID in (1,3,5,7,9) """

viewB.save() # <-- Important! don't lose keys!

success, results = viewB.create()
```

We've used the same private key for the table and the view.  This is NOT required, but is convenient if you are building a view atop only one table.  

Each object comes with a pre-built ```recommended_filename``` which acts as the default for ```save()``` and ```load()```.  

```python
print( tableA.recommended_filename )
print( viewB.recommended_filename )
print( suzy.recommended_filename )
```

Once you're done, it's best practice to clean up.  

```python
viewB.drop()
tableA.drop()
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "spaceandtime",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "space and time, sxt, spaceandtime, verifiable, database, web3, blockchain, data warehouse, data",
    "author": null,
    "author_email": "Stephen Hilton <stephen.hilton@spaceandtime.io>",
    "download_url": "https://files.pythonhosted.org/packages/21/5c/f17f447e44feec1f3b5f95356bd0cb5243695a1026d04e860e984a8e498f/spaceandtime-1.1.25.tar.gz",
    "platform": null,
    "description": "\n  \n  \n\n## Python Space and Time SDK \n\n  \n\nPython SDK for Space and Time Gateway (python version >= 3.11)\n\n  \n\n## Installation Instructions\n\n  \n\n_Note: The recommended approach to storing keys is using an `.env` file. \nFor more information, please see: https://docs.spaceandtime.io/docs/dotenv_\n\n  \n\n```sh\npip install spaceandtime\n```\n\n \n  \n\n### Getting Started\n\n```python\n# Initializing the Space and Time usage.\nfrom spaceandtime import SpaceAndTime\n\nsxt = SpaceAndTime()\nsxt.authenticate()\n\nsuccess, rows = sxt.execute_query(\n\t'select * from POLYGON.BLOCKS limit 5')\nprint( rows )\n```\n\nThe authentication without arguments will seek out a default `.env` file and use credentials found there.  It also supports passing in a specific ```filepath.env``` or simply supplying ```user_id``` and ```private_key```.\n\nThe generated ``access_token`` is valid for 25 minutes and the ``refresh_token`` for 30 minutes.\n\nThere are a number of convenience features in the SDK for handling return data sets. By default, data sets are returned as a list-of-dictionaries, however can be easily turned into other formats, such as CSV.\n\n```python\n# use triple-quotes to insert more complicated sql:\nsuccess, rows = sxt.execute_query(\"\"\"\n\tSELECT \n\tsubstr(time_stamp,1,7) AS YrMth\n\t,count(*) AS block_count\n\tFROM polygon.blocks \n\tGROUP BY YrMth\n\tORDER BY 1 desc \"\"\" )\n\n# print results as CSV\nprint( sxt.json_to_csv(rows) )\n```\n\nMore data transforms will be added over time.\n\n### SXTUser Object\n\nAll SQL requests are handled by an authenticated user object.  The ```sxt``` wrapper object contains a 'default user' object for simplicity, managing and authenticating as needed.  It is however exposed if needed:\n\n```python\nprint( sxt.user )\n```\n\nYou can also manage users directly.  This allows you to load and authenticate multiple users at a time, in case your application needs to manage several accounts.\n\n_**All interaction with the network requires an authenticated user.**_\n\nThe user object owns the authenticated connection to the network, so all requests are submitted by a user object.\n\n```python\n# Multiple Users\nfrom spaceandtime import SXTUser\n\nsuzy = SXTUser('./users/suzy.env', authenticate=True)\n\nbill = SXTUser()\nbill.load()         # defaults to \"./.env\"\nbill.authenticate()\n\n# new user\npat = SXTUser(user_id='pat')\npat.new_keypair()\npat.api_url = suzy.api_url\npat.save() # <-- Important! don't lose keys!\npat.authenticate()\n```\n\nThere is also some capability to administer your subscription using the SDK.  This capability will expand more over time.\n\n```python\n# suzy invites pat to her subcription:\nif suzy.user_type in ['owner','admin']: \n\tjoincode = suzy.generate_joincode()\n\tsuccess, results = pat.join_subscription(joincode)\n\tprint( results )\n```\n\n\n\n### DISCOVERY\n\nThere are several discovery functions that allow insight to the Space and Time network metadata.\n\n\n```python\n# discovery calls provide network information\nsuccess, schemas = sxt.discovery_get_schemas()\n\nprint(f'There are {len(schemas)} schemas currently on the network.')\nprint(schemas)\n```\n\n\n### Creating Tables\n\nThe SDK abstracts away complexity from making a new table into a Table object.  This object contains all needed components to be self-sufficient _EXCEPT_ for an authenticated user object, which is required to submit the table creation to the network.\n\n```python\n# Create a table\nfrom spaceandtime import SXTTable, SXTTableAccessType\n\ntableA = SXTTable(name = \"SXTTEMP.MyTestTable\", \n\t\t\t\tnew_keypair = True, \n\t\t\t\tdefault_user = sxt.user,\n\t\t\t\tlogger = sxt.logger,\n\t\t\t\taccess_type = SXTTableAccessType.PERMISSSIONED)\n\ntableA.create_ddl = \"\"\"\n\tCREATE TABLE {table_name} \n\t( MyID         int\n\t, MyName       varchar\n\t, MyDate       date\n\t, Primary Key(MyID) \n\t) {with_statement}\n\"\"\" \n\n# create new biscuits for your table\ntableA.add_biscuit('read',  tableA.PERMISSION.SELECT )\n\ntableA.add_biscuit('write', tableA.PERMISSION.SELECT, \n\t\t\t\t\t\t\ttableA.PERMISSION.INSERT, \n\t\t\t\t\t\t\ttableA.PERMISSION.UPDATE, \n\t\t\t\t\t\t\ttableA.PERMISSION.DELETE,\n\t\t\t\t\t\t\ttableA.PERMISSION.MERGE )\n\ntableA.add_biscuit('admin', tableA.PERMISSION.ALL )\n\ntableA.save() # <-- Important!  Don't lose your keys!\n\n# create with assigned default user\nsuccess, results = tableA.create()  \n```\n\n\nThe ```table.create_ddl``` and ```table.with_statement``` property will substitute {names} to replace with class values.  In the example above, the ```{table_name}``` will be replace with ```tableA.table_name``` and the ```{with_statement}``` will be replaced with a valid WITH statement, itself with substitutions for ```{public_key}``` and ```{access_type}```.\n\nNote, if the ```{with_statement}``` placeholder is absent, the table object will attempt to add dynamically.\n\nWhen adding biscuits, they can either be added as string tokens, or as SXTBiscuit type objects, or as a list of either.\n\nThe ```tableA.save()``` function will save all keys, biscuits, and table attributes to a shell-friendly format, such that you could execute the file in shell and load all values to environment variables, for use in other scripting. For example,\n\n```sh\nStephen~$ . ./table--SXTTEMP.New_TableName.sql\nStephen~$ echo $TABLE_NAME\n  SXTTEMP.New_TableName\n```\nThis allows table files created in the python SDK to be used with the SxT CLI. \n\n\n### Insert, Deletes, and Selects\n\nThere are helper functions to assist quickly adding, removing, and selecting data in the table.  Note, these are just helper functions for the specific table object - for more general SQL interface, use the ```sxt.execute_query()``` function. \n\n```python\nfrom pprint import pprint # for better viewing of data\n\n# generate some dummy data\ndata = [{'MyID':i, 'MyName':chr(64+i), 'MyDate':f'2023-09-0{i}'} for i in list(range(1,10))]\n\n# insert into the table\ntableA.insert.with_list_of_dicts(data)\n\n# select out again, just for fun\nsuccess, rows = tableA.select()\npprint( rows )\n\ntableA.delete(where='MyID=6')\n\n# one less than last time\nsuccess, rows = tableA.select()\npprint( rows )\n```\n\n### Creating Views \n\nThe SXTView object inherits from the same base class as SXTTable, so the two are very similar.  One notable difference is a view's need for a biscuit for each table referenced.  To add clarity and remind of this requirement, a view contains a ```table_biscuit``` property. Also note that views don't need DML PERMISSIONS, like insert or delete.\n\n```python\n# create a view \nfrom spaceandtime import SXTView\n\nviewB = SXTView('SXTTEMP.MyTest_Odds',\n \t\t\t\tdefault_user=tableA.user, \n\t\t\t\tprivate_key=tableA.private_key, \n\t\t\t\tlogger=tableA.logger)\n\nviewB.add_biscuit('read', viewB.PERMISSION.SELECT)\nviewB.add_biscuit('admin', viewB.PERMISSION.ALL) \nviewB.table_biscuit = tableA.get_biscuit('admin')\n\nviewB.create_ddl = \"\"\"\n\tCREATE VIEW {view_name} \n\t{with_statement} \n\tAS\n\tSELECT *\n\tFROM \"\"\" + tableA.table_name + \"\"\"\n\tWHERE MyID in (1,3,5,7,9) \"\"\"\n\nviewB.save() # <-- Important! don't lose keys!\n\nsuccess, results = viewB.create()\n```\n\nWe've used the same private key for the table and the view.  This is NOT required, but is convenient if you are building a view atop only one table.  \n\nEach object comes with a pre-built ```recommended_filename``` which acts as the default for ```save()``` and ```load()```.  \n\n```python\nprint( tableA.recommended_filename )\nprint( viewB.recommended_filename )\nprint( suzy.recommended_filename )\n```\n\nOnce you're done, it's best practice to clean up.  \n\n```python\nviewB.drop()\ntableA.drop()\n```\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2023 Space and Time  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
    "summary": "SDK for Space and Time verifiable database",
    "version": "1.1.25",
    "project_urls": {
        "Docs": "https://docs.spaceandtime.io",
        "Documentation": "https://docs.spaceandtime.io",
        "Github": "https://github.com/spaceandtimelabs/SxT-Python-SDK",
        "Homepage": "https://spaceandtime.io"
    },
    "split_keywords": [
        "space and time",
        " sxt",
        " spaceandtime",
        " verifiable",
        " database",
        " web3",
        " blockchain",
        " data warehouse",
        " data"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "36f3c6111b6feed1a9f92a13de63c362ff7e87282ed53f22339e3289ea76fbf3",
                "md5": "649a6f84d16919464cc6108a6be13f50",
                "sha256": "7349af9fca0d0b83834aefe016b326e086a566a66a74bae495d7c1577cb99538"
            },
            "downloads": -1,
            "filename": "spaceandtime-1.1.25-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "649a6f84d16919464cc6108a6be13f50",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 50834,
            "upload_time": "2024-05-18T23:13:48",
            "upload_time_iso_8601": "2024-05-18T23:13:48.904147Z",
            "url": "https://files.pythonhosted.org/packages/36/f3/c6111b6feed1a9f92a13de63c362ff7e87282ed53f22339e3289ea76fbf3/spaceandtime-1.1.25-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "215cf17f447e44feec1f3b5f95356bd0cb5243695a1026d04e860e984a8e498f",
                "md5": "c523ec9887084041f79a97abe0b189c4",
                "sha256": "da99e56cfb582a6488d6b53f491151aedf67cf5615adadc670ccaf07c3676de1"
            },
            "downloads": -1,
            "filename": "spaceandtime-1.1.25.tar.gz",
            "has_sig": false,
            "md5_digest": "c523ec9887084041f79a97abe0b189c4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 54865,
            "upload_time": "2024-05-18T23:13:50",
            "upload_time_iso_8601": "2024-05-18T23:13:50.554779Z",
            "url": "https://files.pythonhosted.org/packages/21/5c/f17f447e44feec1f3b5f95356bd0cb5243695a1026d04e860e984a8e498f/spaceandtime-1.1.25.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-18 23:13:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "spaceandtimelabs",
    "github_project": "SxT-Python-SDK",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "spaceandtime"
}
        
Elapsed time: 0.28260s