Welcome | Get started | Dive into Lino | Contribute | Topics | Reference | More

google : Synchronization with Google

This page gives developer information about the lino_xl.lib.google plugin, which adds google calendar and contacts synchronization functionality to your Lino application. See also google : Synchronization with Google.

This page is a tested document and the following instructions are used for initialization:

>>> from lino import startup
>>> startup('lino_book.projects.noi1e.settings.demo')
>>> from lino.api.doctest import *

Plugin settings

This plugin adds the following settings, which a site maintainer can configure in the settings.py.

google.contacts_model
Type:

str

Value:

contacts.Person

google.num_retries

How many times to call GoogleAPI in case of googleapiclient.errors.HttpError

Type:

int

Value:

3

google.client_secret_file

JSON formatted GoogleAPI client secret.

Type:

pathlib.Path

Obtainable for google. See: this thread.

google.scopes

The access list to google API.

Type:

list

>>> pprint(dd.plugins.google.scopes)
['https://www.googleapis.com/auth/userinfo.profile',
 'https://www.googleapis.com/auth/userinfo.email',
 'https://www.googleapis.com/auth/contacts',
 'https://www.googleapis.com/auth/calendar',
 'https://www.googleapis.com/auth/calendar.events']
google.entry_state_translation

Translate EntryState into google status.

Type:

tuple[tuple[str, tuple[str, ...]]]

Value:

(('confirmed', ('confirmed', )), ('tentative', ('tentative', )), ('cancelled', ('cancelled', )))

The first value of the inner tuples is the corresponding Google event status for the EntryState names in the second value (which is also a tuple).

google.guest_state_translation

Translate between possible values in Google and Lino guest state choices.

Type:

tuple[tuple[str, tuple[str, ...]]

Value:

(('needsAction', ('needsAction', )), ('declined', ('decliend', )), ('tentative', ('tentative', )), ('accepted', ('accepted', )))

Add more items on the second item of the inner toples so that they translate to the first item on the inner tuple.

Model mixins

class lino_xl.lib.google.AccessLockable

A model mixin to lock access to the database object (on each database query), allowing only one transaction to such objects.

Inherits from Modified.

On calling the save method. The object is unlocked automatically and should not be used at all afterwards. To use it further fetch it from the database again, and further access will be locked automatically.

This might be dangerous in case a locked instance is lost from a python session, and could be hard to get this object back from the database. Workarounds: Use the unlock_all() or unlock_objects() to modify them at the database level. Or get a list of pk(s) using get_locked_objects_pk() and use _force_get() instead. The following methods are available for troubleshooting:

classmethod unlock_all()

Unlocks all database objects.

classmethod unlock_objects(pk_list: list)

Given a list of pk(s) it unlocks them at the database level.

classmethod get_locked_objects_pk()

Returns a list of pk(s) of the currently locked objects.

classmethod _force_get(pk: int)

Given a pk it returns a locked database object. Use this method only for troubleshooting.

class lino_xl.lib.google.SyncToken

A model mixin inherits from AccessLockable and UserAuthored.

sync_token

A CharField to store nextSyncToken retrieved from Google API call.

page_token

A CharField to store nextPageToken retrieved from Google API call.

class lino_xl.lib.google.GoogleSynchronized

Google's related database models inherits from this mixin.

google_id

Used in making reference to the object stored in Google's database.

synchronize_with_google(self, user: User | None) bool

Decides whether the entry is synchronizable with Google.

Parameters:

user (Optional[User]) -- The user who's Google account lino is synchronizing with.

class lino_xl.lib.google.GoogleCalendarSynchronized

A subclass of GoogleSynchronized.

modified

Keeps the timestamp of the last modification of the Calendar as an entry.

Type:

datetime.datetime

Helps in synchronization with Google.

insert_or_update_into_google(self, resource, synchronizer) None

Insert or updates the calendar entry with google.

Parameters:
  • resource -- Google calendar API resource. Can be obtained by calling Resource.calendars()

  • synchronizer -- An instance of Synchronizer

classmethod get_outward_insert_update_queryset(cls, user)

This method returns a queryset of Calendar that are not stored in Google or should be updated.

Parameters:

user -- An instance of User

Returns:

django.db.models.query.QuerySet

classmethod delete_google_calendar(cls, cal: dict, synchronizer) None

This method deletes a Calendar at sync time when the calendar is deleted from the Google calendar.

Parameters:
  • cal (dict) -- Dictionary of attributes of the deleted calendar.

  • synchronizer -- An instance of Synchronizer

Also deletes the DeletedEntry record from the database to keep it clean.

classmethod sync_deleted_records(cls, resource, synchronizer) None

Deletes calendars by looking at DeletedEntry from Google calendar.

Parameters:
  • resource -- Google calendar API resource. Can be obtained by calling Resource.calendars()

  • synchronizer -- An instance of Synchronizer

classmethod insert_or_update_google_calendar(cls, cal: dict, synchronizer)

Inserts or updates a calendar entry and the default Room.

Parameters:
Returns:

A tuple of the saved calendar entry and the default room.

Return type:

tuple[Calendar, Room]

class lino_xl.lib.google.GoogleCalendarEventSynchronized

A subclass of GoogleSynchronized.

classmethod delete_google_event(cls, cal: dict, synchronizer) None

This method deletes a Event at sync time when the event is deleted from the Google calendar.

Parameters:
  • event (dict) -- Dictionary of attributes of the deleted event.

  • synchronizer -- An instance of Synchronizer

Also deletes the DeletedEntry record from the database to keep it clean.

classmethod sync_deleted_records(cls, resource, synchronizer) None

Deletes events by looking at DeletedEntry from Google calendar.

Parameters:
  • resource -- Google calendar API resource. Can be obtained by calling Resource.events()

  • synchronizer -- An instance of Synchronizer

classmethod get_outward_insert_update_queryset(cls, user)

This method yields Event (s) which are not stored in Google or should be updated.

Parameters:

user -- An instance of User

Returns:

Generator[Event, None, None]

insert_or_update_into_google(self, resource, synchronizer) None

Insert or updates the events into Google.

Parameters:
  • resource -- Google calendar API resource. Can be obtained by calling Resource.events()

  • synchronizer -- An instance of Synchronizer

classmethod insert_or_update_google_event(cls, event: dict, room, synchronizer)

Inserts or updates a calendar entry and related Room and Guest 's.

Parameters:
Returns:

Saved calendar event entry.

Return type:

Event.

class lino_xl.lib.google.GoogleContactSynchronized

A subclass of GoogleSynchronized.

classmethod delete_google_contact(cls, contact: dict, synchronizer) None

This method deletes a Contact at sync time when the contact is deleted from Google.

Parameters:
  • contact (dict) -- Dictionary of attributes of the deleted contact.

  • synchronizer -- An instance of Synchronizer

Also deletes the DeletedContact record from the database to keep it clean.

classmethod sync_deleted_records(cls, resource, synchronizer) None

Deletes contacts by looking at DeletedContact from Google.

Parameters:
  • resource -- Google people API resource. Can be obtained by calling Resource.people()

  • synchronizer -- An instance of Synchronizer

classmethod get_outward_insert_update_queryset(cls, user: users.User = None)

Returns contacts insertable or updatable into Google.

Parameters:

user -- An instance of User

Returns:

django.db.models.QuerySet

insert_or_update_into_google(self, resource, synchronizer)

Insert or updates the contact into Google.

Parameters:
  • resource -- Google people API resource. Can be obtained by calling Resource.people()

  • synchronizer -- An instance of Synchronizer

classmethod insert_or_update_google_contact(cls, contact: dict, synchronizer)

Inserts or updates a contact Contact.

Parameters:
Returns:

Saved contact entry

Return type:

Contact

Choices and choicelists

Defines ChoiceList(s) and some utility functions.

lino_xl.lib.google.google_status(state: EntryState | GuestState) str | None
Parameters:

state -- Takes either a EntryState or a GuestState.

Returns:

An str as status acceptable by Google.

Internally it works by looking at state_translation either google.entry_state_translation when the input parameter is an instance of an EntryState or google.guest_state_translation when the input parameter is an instance of a GuestState. It returns None if a value is not found for a corresponding state.

>>> google.google_status(cal.EntryStates.tentative)
'tentative'
class lino_xl.lib.google.AccessRoles

Keeps the choices for the type of access to a Google calendar.

Used for checking whether a user can insert into a Google calendar. The available values are freeBusyReader (read public info only), reader, writer and owner.

>>> rt.show(google.AccessRoles)
======= ================ ==================
 value   name             text
------- ---------------- ------------------
 p       freeBusyReader   Free busy reader
 r       reader           Reader
 w       writer           Writer
 o       owner            Owner
======= ================ ==================

Database objects

class lino_xl.lib.google.CalendarSubscription

A subclass of BaseSubscription.

primary

A boolean field which indicated whether calendar referenced in this subscription is the primary calendar for the user in Google.

access_role

User's access role on the subscribed calendar.

See: AccessRoles

class lino_xl.lib.google.EventSyncToken

A subclass of SyncToken, stores necessary tokens to sync the events updated in a user's google calendar.

subscription

A ForeignKey pointing to a CalendarSubscription object.

class lino_xl.lib.google.CalendarSyncToken

A subclass of SyncToken, store the necessary tokens to sync the calendars updated on a user's google account.

class lino_xl.lib.google.DeletedEntry

Keeps a record of the natively deleted Calendar or Event for deleting from Google when the next sync is run.

calendar

A boolean field which says whether the deleted item is a Calendar if not it is an Event.

Type:

bool

Value:

False

event_id

Takes the value of the Event.google_id when the deleted record is an Event otherwise an empty string.

Type:

str

calendar_id

Takes the value of the Calendar.google_id

Type:

str

If the deleted record is an Event it takes the google_id from the Calendar in which the deleted Event belongs to.

class lino_xl.lib.google.Contact

Keeps a reference to a google contact.

A subclass of UserAuthored, GoogleContactSynchronized and Modified.

contact

A ForeignKey pointing to google.contacts_model.

class lino_xl.lib.google.DeletedContact

Keeps meta information of a deleted contact to sync with google upon next synchronization.

A subclass of UserAuthored.

contact_id

The google resourceName.

class lino_xl.lib.google.ContactSyncToken

Stores the nextSyncToken and nextPageToken from google.

A subclass of SyncToken.

class lino_xl.lib.google.SyncSummary

Database model to store the summaries of a Synchronizer.sync() session.

Subclass of UserAuthored and Created

halted

A BooleanField indicate whether the sync session has failed.

stats

A TextField containing the textual representation of synchronization session statistics.

class lino_xl.lib.google.FailedForeignItem

Database model to store the foreign objects failed to put into the local database.

job

A ForeignKey pointing to the corresponding SyncSummary.

value

A JSONField containing the actual remote object.

item_class

A ForeignKey pointing to the related database model (contenttypes.ContentType) specifying the item synchronization class.

Interaction with other plugins

This plugin adds the following method get_country to lino.modlib.users.User model:

class lino.modlib.users.User
get_contact()

Returns the user's country.

Synchronization

Calendar and contacts synchronization in Lino with Google works in both ways. Lino application can fetch entries from Google as well as it can insert and update entries into Google.

By default google.contacts_model are not synchronisable with google unless they pointed to by some Contact instance.

class lino_xl.lib.google.FailedEntries

A subclass of typing.NamedTuple. And has the following attributes.

calendars

Contains reference to the Calendar instance(s) that failed to sync with Google.

Type:

list[django.db.models.QuerySet]

Value:

[]

events

Contains reference to the Event instance(s) that failed to sync with Google.

Type:

list[django.db.models.Model]

Value:

[]

contacts

Contains reference to the Contact instance(s) that failed to sync with Google.

Type:

list[django.db.models.QuerySet]

Value:

[]

foreign_item

Objects fetched from the remote and failed to update (/ put) on the local database.

Type:

list[tuple[dd.Model, dict]]

The first item of the tuple is any non-abstract subclass of dd.Model and the second item is the fetched object from the remote.

Value:

[]

class lino_xl.lib.google.Synchronizer

The class that wraps the synchronization functionality.

_failed_entries

Keeps reference to the database objects that failed to sync with google from the last sync() call.

Type:

FailedEntries

failed_entries

Keeps reference to the database objects that failed to sync with google in the running sync() call.

Type:

FailedEntries

user

The User, whose records should be synchronized.

setup(user) None

Sets up the user scope and initializes necessary data objects.

sync() self

Synchronizes latest changes with Google.

Getting GoogleAPI credentials

Log in to your Google Developer Console.

Create a project in the console if you don't have one already.

In the google console: Navigate to APIs & Services >> Enabled APIs & Services then click on + ENABLE APIS AND SERVICES afterwards search for Google People API and Google Calendar API and enable them.

For detailed information follow this Google API Console Help page.

Navigate to APIs & Services ‣ Credentials then click on + CREATE CREDENTIALS choose OAuth client ID. Set the Application type to Web application. In the Authorized redirect URIs section click on + ADD URI and put you matching URI to the following regex and hit CREATE:

>>> your_server_host_name = r".*"
>>> uri_pattern = r"^http(s)?://" + your_server_host_name + r"/oauth/complete/google/$"

Click on the DOWNLOAD JSON button to download the credentials.

Set the following config on your settings.py:

>>> class Site(...): 
...     ...
...     def get_plugin_configs(self):
...         ...
...         yield 'google', 'client_secret_file', path_to_your_downloaded_json
...     ...

Navigate to APIs & Services ‣ OAuth consent screen and put the emails of some test users.

And that's almost it for getting Google API credentials.