Skip to main content

Shared data for Python

Project description

Shared

Shared is the Python library to store, expose, read, and edit collections of data. It's part of the Pyrustic Open Ecosystem.

Installation | Reference

Overview

Shared contains two main classes: Jason and Store.

Jason allows individual access to json files that are likely to be manually edited by a human user. Jason is relevant for managing configuration files.

Store allows you to store collections of data without worrying about how they are actually saved. Store is relevant for application data storage and persistent data caching.

Jason

Let's play with Jason:

from shared import Jason


# access 'my-data.json'
jason = Jason("my-data")
# let's initialize the content of 'my-data'
if jason.new:
    jason.data = {"name": "alex", "job": "angelist"}

jason.data["job"] = "evangelist"

jason.save()  # persisted !

The same stuff with two twists:

from shared import Jason

# default data to init my 'my-data.json'
DEFAULT_DATA = {"name": "alex", "job": "angelist"}

# access 'my-data.json'
jason = Jason("my-data", default=DEFAULT_DATA)

# jason.data is either an instance of
# shared.SharedDict or shared.SharedList
data = jason.data

data["job"] = "evangelist"

# yes, you can call the .save method directly
# from the data returned by the jason.data property
data.save()  # persisted !

By default, the json files are saved in the in $HOME/PyrusticData/shared. You can change the location to fit your needs:

from shared import Jason

LOCATION = "/home/alex/app-data"

# access 'my-data.json'
jason = Jason("my-data", location=LOCATION, readonly=True)

# when you set readonly to True, you can't anymore edit the content !

Two more tips:

from shared import Jason


# access 'my-config.json'
jason = Jason("my-config", autosave=True, default=[])

# when you set autosave to True, you don't anymore need
# to call the method .save() !

jason.data.append("batman")  # persisted ! yeah yeah !

# you can delete the jason file (assuming that readonly is False)
jason.delete()

print(jason.deleted)  # output: True

Now let's discover the class shared.Store !

Store

Store data:

from shared import Store

# data
people = {"Jack": "male", "Jane": "female"}  # dict
planets = ["Mars", "Venus", "Jupiter"]  # list
colors = {"red", "green", "blue"}  # set

# let's persist the data in the store 'my-store'
store = Store("my-store")
store.set("people", people)  # set the entry 'people'
store.set("planets", planets)  # set the entry 'planets'
store.set("colors", colors)  # set the entry 'colors'

# Done !

Read data from another script:

from shared import Store

# let's open the shared store in readonly mode
store = Store("my-store", readonly=True)

# get data from the shared store 'my-store'
people = store.get("people") # get the entry 'people'
planets = store.get("planets") # get the entry 'planets'
colors = store.get("colors") # get the entry 'colors'

print(people)
# output: {'Jack': 'male', 'Jane': 'female'}

print(planets)
# output: ['Mars', 'Venus', 'Jupiter']

print(colors)
# output: {'red', 'green', 'blue'}

Since we're all consenting adults here, you can edit the data from another script:

from shared import Store

store = Store("my-store")
planets = store.get("planets")

# the object 'planets' is a SharedList
print(type(planets))
# output: <class 'shared.SharedList'>

# you can update its content like a standard list
planets.append("Earth")

# then you can save the updated collection
planets.save()

Maybe you need your collection to be automatically saved when its content changes:

from shared import Store

# the 'autosave' feature will save your collections
# whenever their content change
store = Store("my-store", autosave=True)
planets = store.get("planets")

planets.append("Saturn")  # done ! collection updated and saved !

Shared comes with an easy-to-use command line interface:

$ shared store "my-store" "planets"
['Mars', 'Venus', 'Jupiter', 'Earth', 'Saturn']

$ shared store "my-store" "colors"
{'red', 'green', 'blue'}

$ shared store "my-store" "people"
{'Jack': 'male', 'Jane': 'female'}

Type help in the command line interface to display a short manual.

Now you are wondering where Shared stores collections and in what file format.

Well, the file format is JSON, and the default location is in the home directory. More precisely, the default directory to keep stores is: $HOME/PyrusticData/shared.

$ shared store "my-store"
/home/alex/PyrusticData/shared
- colors (set)
- people (dict)
- planets (list)

You can change the default location:

from shared import Store

PRIVATE_DATA_DIRECTORY = "/home/alex/private"
store = Store("secret-store-42", location=PRIVATE_DATA_DIRECTORY)

# the store 'secret-store-42' will be created inside
# the directory '/home/alex/private'

Private stores are still accessible through the command line interface. You will just need to change the current working directory:

$ cd "/home/alex/private"

$ shared store "secret-store-42"
- Empty store -

As you can see, Shared is great for sharing collections with other software, or just used as private data storage. The command line interface makes things more wonderful.

Wait... can you store binary data with Shared ?

Yes, you can:

from shared import Store

store = Store("my-store")

with open("/home/alex/selfie.png", "rb") as file:
    data = file.read()
    store.set("selfie", data)  # set the entry 'selfie'

From the command line, you can copy this binary data into an arbitrary file:

$ shared store "my-store" "selfie" > "/home/alex/new.png"

Or you can do the same thing but in reverse, i.e. store the binary data from the command line:

$ shared store "my-store" "selfie" bin "/home/alex/selfie.png"
Successfully updated the entry 'selfie' !

Then programmatically copy this binary data to an arbitrary file:

from shared import Store
from shutil import copyfile

store = Store("my-store")
source_path = store.get("selfie")  # get the bin entry 'selfie'
destination_path = "/home/alex/new.png"

# copy the content from source to destination
copyfile(source_path, destination_path)

Do you care about the space available on your hard drive ?

Well you can easily delete any entry. Programmatically:

from shared import Store

store = Store("my-store")
# delete the entry 'selfie'
store.delete("selfie")

or from the command line interface:

$ shared del "my-store" "selfie"
Successfully deleted !

You can decide to be a badass and delete the store. Programmatically:

from shared import Store

store = Store("my-store")
store.delete()  # data collections, binary data, and meta data are gone

or from the command line interface:

$ shared del "my-store"
Successfully deleted !

Between us, do you trust the delete feature ? Here is a snippet of the code which shows that the directory to be deleted must have a particular signature, otherwise it will not be deleted:

def delete(self, *names):

    ...

    if self._readonly:
        raise ReadonlyError
    # the directory to delete is checked
    # to be sure that it has the store signature
    if not valid_store(self._store_path):
        return False
    if not names:  # delete store
        shutil.rmtree(self._store_path)

    ...

Are you wondering how the autosave feature works ? Under the hood, Shared uses the awesome library probed.

Probed collections let you know when their content change (with 1 more twist !).

Discover Probed !

Installation

Do you like Shared ? Guess what, it's available on PyPI:

$ pip install shared

Related projects

Both Shared and Probed are part of the Pyrustic Open Ecosystem.

Looking for an awesome theme for your desktop application ? Check Cyberpunk Theme !

Do you want to create a popular theme for Python desktop apps ? Check TkStyle !

Do you dream to add the autocomplete feature to your desktop app ? Check Suggestion !

Struggling with GUI+multithreading ? Check Threadom !

Do you like the project(s) and want to help ? Tell your friends about the project(s) !

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shared-0.0.5.tar.gz (14.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shared-0.0.5-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file shared-0.0.5.tar.gz.

File metadata

  • Download URL: shared-0.0.5.tar.gz
  • Upload date:
  • Size: 14.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.6.1 requests/2.9.1 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.54.0 CPython/3.5.2

File hashes

Hashes for shared-0.0.5.tar.gz
Algorithm Hash digest
SHA256 5f0f1324b45c6954f4079113a0b1d5a76790165f71c5fba676f97eca7d8943a1
MD5 0de2ad45f20fb27e2a47fba335cebe2b
BLAKE2b-256 94e8831e5800bc04890008d7c9a70ab6a5024478e0f4ef89a7266a29b29ff3fe

See more details on using hashes here.

File details

Details for the file shared-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: shared-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 17.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.6.1 requests/2.9.1 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.54.0 CPython/3.5.2

File hashes

Hashes for shared-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 eaa5c92f4bcfdf006e1b6369d85656257ecb230412c622d8fb40a7503313bede
MD5 94f6fef6cc19343b620399d269c1152a
BLAKE2b-256 f7fbfda51cba71b1855b9aa90e59b4c59589892140a1be028a050ec28a36d88d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page