[Share code] ReminderStore - not what Apple intended
From the readme:
Key-value store using iOS Reminders for persistence and distribution across iOS devices.
ReminderStore is a Pythonista persistence provider. It uses the
remindersmodule to store the values in a specific list in the iOS Reminders app. If you set that list to be distributed across your iOS devices, you get a free cloud-based storage for your app data, suitable for prototyping different distributed use cases.
Create a store object providing the name of the Reminders list to be created/used:
store = ReminderStore(namespace, to_json=False, cache=False)
Use the store object to store, retrieve, list and delete items:
store['key'] = 'value'
for key in store: print store[key]
If you want to store structures instead of plain strings, set
to_json=True. Store and retrieval operations will then serialize and restore the values to and from JSON.
cache=Truereduces direct access to the Reminders app. Use the
refresh_cache()method to refresh the cache and get information on any background changes. See Notes below for more details.
- Key is stored as the title of the reminder, and value in the notes field.
- Reminder titles are not unique, but ReminderStore uses an intermediate dict to enforce uniqueness. Results are likely to be unproductive if you create duplicate titles manually.
- Key is used as-is if it is a plain or unicode string. Otherwise str() is called on key before using it.
- By default, ReminderStore goes to the Reminders app to get the latest information. This is somewhat inefficient since checking for new items always requires loading the full list. There are two cases where you might to prefer to activate the intermediate caching instead:
- If you have no-one making any updates remotely, cache will be more efficient and will never need manual refreshing.
- If you want to get more control over when any background changes are applied in your app, use the caching and call
refresh_cacheto check and process changes. The method returns None if there are no changes, or a dict with
changedsets if there are changes. Each set contains the keys of the stored items that were inserted, deleted or had their contents modified, respectively. You can use this info to e.g. remove deleted items from the UI, or inform the user of a conflict and let them decide which version to keep.
- Note that iOS Reminders app provides no support for complex atomic transactions or referential integrity between items.
This is a quite creative idea. I wonder if it can be extended to provide an alternative solution to sync user scripts across devices. A few existing tools use Dropbox or webdav servers. But iCloud would definitely be an attractive option.
My guess is that one could use both RemiderStore and pyzipista by @marcus67 to achieve the sync. Basically pyzipista provides serialisation of files and folders and RemiderStore provides data transport and communication. Some design is likely needed to take care how data and their metadata are stored in the reminder. Is there a character limit of the notes field? I tried with over 60K and it worked fine.
Thought about it, and concluded that it is certainly possible, but probably a bad idea for larger amounts of larger files.
I do not know and have not had time to test what kind of a size limit there is on the notes section of a reminder, and whether it gives any error or just cuts the extra if such a limit is reached.
Also, the reminders module is such that there is no way to list reminders and just load one - it behaves like it loads the whole list at once. This can be cumbersome if there are several large files, all in memory at the same time.
Hmm, have to take a closer look at the module implementation.
You can share reminder lists with others... This might be a cool technique for free device-to-device comms in a multiplayer game with delayed delivery when a player is not online.
Yes. Cool idea. Messages would need to be encrypted, though, otherwise opening the Reminders app and tampering with results might be too tempting...
My Pythonista-fu is weak. I cannot find the code for the reminders module.
import inspect, reminders print(inspect.getsource(reminders))
is the usual approach viewing the source of a module but it fails because reminders is a builtin module so no source is provided.
Encryption could be done via https://github.com/dlitz/pycrypto which is provided in Pythonista.
@omz: When you are not busy otherwise, could you please share/check whether the reminders implementation is such that when getting all the reminders for a list, it only creates proxy objects to the Reminders app, or whether it creates instantiated objects, i.e. reading all the data into Pythonista?
@mikael It looks very much like
Calendar, etc. are just proxies. All of their attributes are really
getset_descriptors (though that is the standard for most C classes, not just proxies) and
gc.get_referentsshows no Python objects being referred to (though there might still be C data).
@dgelessus, thanks. If that is true, creating a iCloud-based file sync between devices would seem feasible. I could take it on once my current project is done.
Reminderclass is essentially just a wrapper for the Objective-C class
EKReminder(from the EventKit framework). How and when exactly the data for each reminder is fetched from the database is basically an implementation detail, and it's hard to tell without having access to the source code.