v 11.0 v 12.0 Third Party 1846
Download for v 12.0 Deploy on Odoo.sh
Required Apps Website (website)
Included Dependencies
Lines of code 6054
Technical Name sync
LicenseSee License tab
Websitehttps://t.me/sync_studio
Also available in version v 13.0 v 15.0 v 14.0 v 11.0
You bought this module and need support? Click here!
Required Apps Website (website)
Included Dependencies
Lines of code 6054
Technical Name sync
LicenseSee License tab
Websitehttps://t.me/sync_studio
Also available in version v 13.0 v 15.0 v 14.0 v 11.0

Sync Studio

Synchronize anything with anything

Version: v12.0.3.0.2


Tested and maintained by
IT Projects Labs
Assitance: help@itpp.dev

The most flexible integration tool

Easy to adjust for your needs!

Logs are available from UI

Easy to debug!

Key integration tools:
  • Cron: execute custom code by cron schedule
  • DB Handler: execute custom code on updates in database
  • Incoming Webhook: process data/event send from external system
  • Manual Triggering: execute custom code manually
Sync Studio comes with few demo integration:
  • Trello-Github
  • Odoo2odoo
  • Telegram
To try them out, install the module in demo mode. Check Documentation tab for usage instructions.

Other solutions are published on Odoo Apps store and more are coming soon!
To get further information and request an assitance, contact us by email: help@itpp.dev

Open Source!

You can find our GitHub repository via Website link above. You are welcome to make a contribution! It could be either:
  • a new module
  • an update to existing module
  • an issue with the data xml file attached (generate one via Action -> Export to XML button in project form)
  • a bug report
  • a feature request
Your contribution will make other Odoo users happy , while IT Projects Labs will assist you on it:
  • we will test the updates
  • we will check bug reports
  • we will document the modules
  • we will port modules to the new Odoo versions

Sincerely,
Ivan Yelizariev

Sync Studio

Installation

  • Make configuration required for queue_job module. In particular:

    • add queue_job to server wide modules, e.g.:

      --load base,web,queue_job
      
  • Install this module in a usual way

  • Install python package that you need to use. For example, to try demo projects install following packages:

    python3 -m pip install python-telegram-bot==12.8 PyGithub py-trello

  • If your Sync projects use webhooks (most likely), be sure that url opens correct database without asking to select one

User Access Levels

  • Sync Studio: User: read-only access
  • Sync Studio: Developer: restricted write access
  • Sync Studio: Manager: same as Developer, but with access to Secrets

Project

  • Open menu [[ Sync Studio ]] >> Projects

  • Create a project

    • Name, e.g. Legacy migration

    • In the Parameters tab

      • Params
        • Key
        • Value
      • Texts: Translatable parameters
      • Secrets: Parameters with restricted access: key values are visible for Managers only
    • In the Evaluation Context tab

      • Evaluation context: predefined additional variables and methods
      • Common_code: code that is executed before running any project's task. Can be used for initialization or for helpers. Any variables and functions that don't start with underscore symbol will be available in task's code.
    • In the Available Tasks tab

      • Name, e.g. Sync products

      • Code: code with at least one of the following functions

        • handle_cron()

        • handle_db(records)

          • records: all records on which this task is triggered
        • handle_webhook(httprequest)

          • httprequest: contains information about request, e.g.

            • httprequest.data: request data
            • httprequest.files: uploaded files
            • httprequest.remote_addr: ip address of the caller.
            • see Werkzeug doc for more information.
          • optionally can return data as a response to the webhook request; any data transferred in this way are logged via log_transmission function:

            • for json webhook: * return json_data

            • for x-www-form-urlencoded webhook: * return data_str * return data_str, status * return data_str, status, headers

              • status is a response code, e.g. 200, 403, etc.
              • headers is a list of key-value tuples, e.g. [('Content-Type', 'text/html')]
        • handle_button()

      • Cron Triggers, DB Triggers, Webhook Triggers, Manual Triggers: when to execute the Code. See below for further information

Job Triggers

Cron

  • Trigger Name, e.g. NIGHTLY_SYNC
  • Execute Every: every 2 hours, every 1 week, etc.
  • Next Execution Date
  • Scheduler User

DB

  • Trigger Name, e.g. PRODUCT_PRICE_CHANGE
  • Model
  • Trigger Condition
    • On Creation
    • On Update
    • On Creation & Update
    • On Deletion
    • Based on Timed Condition
      • Allows to trigger task before, after on in time of Date/Time fields, e.g. 1 day after Sale Order is closed
  • Apply on: records filter
  • Before Update Domain: additional records filter for On Update event
  • Watched fields: fields list for On Update event

Webhook

  • Trigger Name, e.g. ON_EXTERNAL_UPDATE
  • Webhook Type: application/x-www-form-urlencoded or application/json
  • Webhook URL: readonly.

Button

  • Trigger Name, e.g. SYNC_ALL_PRODUCTS

Code

Available variables and functions:

Base

  • env: Odoo Environment

  • log(message, level=LOG_INFO): logging function to record debug information

    log levels:

    • LOG_DEBUG
    • LOG_INFO
    • LOG_WARNING
    • LOG_ERROR
    • LOG_CRITICAL
  • log_transmission(recipient_str, data_str): report on data transfer to external recipients

  • DEFAULT_SERVER_DATETIME_FORMAT

Sync Helpers

For one2one syncronization you can use following helpers.

  • sync_odoo2x(src_list, sync_info, create=False, update=False)
    • sync_info["x"]["create"](odoo_record) -> external_ref: create external record and return reference
    • sync_info["x"]["update"](external_ref, odoo_record) -> external_ref: update external record
    • sync_info["x"]["get_ref"](x): get reference for an item in src_list
  • sync_x2odoo(src_list, sync_info, create=False, update=False)
    • sync_info["odoo"]["create"](x) -> odoo_record: create odoo record from external data
    • sync_info["odoo"]["update"](odoo_record, x) -> odoo_record: update odoo record according to providing external data

Common args:

  • sync_info["relation"]: same as relation_name in set_link, get_link
  • src_list: iterator of x or odoo_record values
  • create: boolean value for "create record if it doesn't exist"
  • update: boolean value for "update record if it exists"

To use helpers, create sync_info with all information, e.g.

EMPLOYEE_SYNC = {
  "relation": "my_system_and_odoo_employee_rel",
  "x": {
    "get_ref": employee2ref,
    "create": employee_create,
    "update": employee_update,
  },
  "odoo": {
    "create": employee_create_odoo,
    "update": employee_update_odoo,
  }
}

Then you can reuse in all syncronizations, e.g.

# on initial fetching records from external system
sync_x2odoo(all_employees_x, EMPLOYEE_SYNC, create=True)
# to push all updates to external system
sync_odoo2x(all_employees_odoo, EMPLOYEE_SYNC, update=True)
# on updating a single record push all updates to external system
sync_odoo2x([employee_odoo], EMPLOYEE_SYNC, update=True)

There is a similar helper for syncronization between two external systems:

  • sync_external(src_list, relation, src_info, dst_info, create=False, update=False)
    • src_info["get_ref"](src_data): get reference for an item in src_list
    • src_info["system"]: e.g. "github"
    • src_info["update"](dst_ref, src_data)
    • src_info["create"](src_data) -> dst_ref
    • dst["system"]: e.g. "trello"

Project Values

  • params.<PARAM_NAME>: project params
  • webhooks.<WEBHOOK_NAME>: contains webhook url; only in tasks' code

Event

  • trigger_name: available in tasks' code only
  • user: user related to the event, e.g. who clicked a button

Asynchronous work

  • add_job(func_name, **options)(*func_args, **func_kwargs): call a function asynchronously; options are similar to with_delay method of queue_job module:
    • priority: Priority of the job, 0 being the higher priority. Default is 10.
    • eta: Estimated Time of Arrival of the job. It will not be executed before this date/time.
    • max_retries: maximum number of retries before giving up and set the job state to 'failed'. A value of 0 means infinite retries. Default is 5.
    • description human description of the job. If None, description is computed from the function doc or name
    • identity_key key uniquely identifying the job, if specified and a job with the same key has not yet been run, the new job will not be added.

Libs

  • json
  • time
  • datetime
  • dateutil
  • timezone
  • b64encode
  • b64decode

Exceptions

  • UserError
  • ValidationError
  • RetryableJobError: raise to restart job from beginning; e.g. in case of temporary errors like broken connection
  • OSError

Evaluation context

Evaluation provides additional variables and methods for a project. For example, for telegram integration is could be method to send message to a telegram user. To make such additional context, you need to make a new module and make extension for sync.project model. Example:

import requests
from odoo import api, fields, models
class SyncProject(models.Model):
    _inherit = "sync.project"
    eval_context = fields.Selection(selection_add=[
        ("my_project", "My Project"),
    ])
    @api.model
    def _eval_context_my_project(self, secrets, eval_context):
        """Additional function to make http request
        * httpPost(url, **kwargs)
        """
        log_transmission = eval_context["log_transmission"]
        log = eval_context["log"]
        def httpPOST(url, **kwargs):
            log_transmission(url, json.dumps(kwargs))
            r = requests.request("POST", url, **kwargs)
            log("Response: %s" % r.text)
            return r.text
        return {
            "httpPost": httpPost
        }

Running Job

Depending on Trigger, a job may:

  • be added to a queue or runs immediatly
  • be retried in case of failure
    • if RetryableJobError is raised, then job is retried automatically in following scheme:
      • After first failure wait 5 minute
      • If it's not succeeded again, then wait another 15 minutes
      • If it's not succeeded again, then wait another 60 minutes
      • If it's not succeeded again, then wait another 3 hours
      • Try again for the fifth time and stop retrying if it's still failing

Cron

  • job is added to the queue before run
  • failed job can be retried if failed

DB

  • job is added to the queue before run
  • failed job can be retried if failed

Webhook

  • runs immediately
  • failed job cannot be retried via backend UI; the webhook should be called again.

Button

  • runs immediately
  • to retry click the button again

Execution Logs

In Project, Task and Job Trigger forms you can find Logs button in top-right hand corner. You can filter and group logs by following fields:

  • Sync Project
  • Sync Task
  • Job Trigger
  • Job Start Time
  • Log Level
  • Status (Success / Fail)

Demo Project: Odoo <-> Telegram

In this project we create new partners and attach messages sent to telegram bot. Odoo Messages prefixed with /telegram are sent back to telegram.

To try it, you need to install this module in demo mode. Also, your odoo instance must be accessible over internet to receive telegram webhooks. Due to telegram requirements, your web server must use http**s** connection.

How it works

Webhook Trigger waits for an update from telegram. Once it happened, the action depends on message text:

  • for /start message (it's sent on first bot usage), we reply with welcome message (can be configured in project parameter TELEGRAM_WELCOME_MESSAGE) and create a partner with Internal Reference equal to <TELEGRAM_USER_ID>@telegram
  • for any other message we attach a message copy to the partner with corresponding Internal Reference

DB trigger waits for a message attached to a telegram partner (telegram partners are filtered by Internal Reference field). If the message has /telegram prefix, task's code is run:

  • a message copy (after removing the prefix) is sent to corresponding telegram user
  • attach report message to the partner record

Configuration

In Telegram:

  • send message /new to @BotFather and follow further instructions to create bot and get the bot token

In Odoo:

  • Activate Developer Mode
  • Open menu [[ Settings ]] >> Technical >> Parameters >> System Parameters
  • Check that parameter web.base.url is properly set and it's accessible over internet (it should not localhost)
  • Open menu [[ Sync Studio ]] >> Sync Projects
  • Select Demo Telegram Integration project
  • Go to Parameters tab
  • Set Secrets:
    • TELEGRAM_BOT_TOKEN
  • Unarchive the project
  • Open Manual Triggers Tab
  • Click button [Run Now] near to Setup task

Usage

In Telegram:

  • send some message to the created bot

In Odoo:

  • Open Contacts/Customers menu
  • RESULT: there is new partner with name Telegram:<YOUR TELEGRAM NAME> (the prefix can be configured in project parameter PARTNER_NAME_PREFIX)
  • Open the partner and attach a log/message with prefix /telegram, e.g. /telegram Hello! How can I help you?
  • Wait few seconds to get confirmation
  • RESULT: you will see new attached message from Odoo Bot with confirmation that message is sent to telegram

In telegram:

  • RESULT: the message is delivered via bot

You can continue chatting in this way

Demo Project: Odoo2odoo

In this project we push partners to external Odoo 12.0 and sync back avatar changes.

To try it, you need to install this module in demo mode.

How it works

DB trigger waits for partner creation. When it happens, task's code is run:

  • creates a copy of partner on external Odoo
    • XMLRPC is used as API
  • gets back id of the partner copy on external Odoo
  • attaches the id to the partner of our Odoo via set_link method

To sync changes on external Odoo we use Cron trigger. It runs every 15 minutes. You can also run it manually. The code works as following:

  • call search_links function to get ids to sync and the oldest sync date
  • request to the external Odoo for the partners, but filtered by sync time to don't load partner without new updates
  • for each of the fetched partner compare its update time with sync date saved in the link
    • if a partner is updated since last sync, then update partner and sync date

Configuration

  • Open menu [[ Sync Studio ]] >> Sync Projects
  • Select Demo Odoo2odoo integration project
  • Go to Parameters tab
  • Set Params: * URL, e.g. https://3674665-12-0.runbot41.odoo.com * DB, e.g. odoo
  • Set Secrets:
    • USERNAME, e.g. admin
    • PASSWORD, e.g. admin
  • Unarchive the project

Usage

Syncing new partner.

  • Open Contacts/Customers menu
  • Create new partner
  • Go back to the project
  • Click Logs button and check that there are no errors
  • Open the external Odoo
    • RESULT: the partner copy is on the external Odoo
    • Update avatar image on it
  • Go back to the Demo Odoo2odoo Integration project in our Odoo
  • Click Available Tasks tab
  • Click [Edit]
  • Go to Sync Remote Partners Updates task
  • Click on Available Triggers tab and go inside CHECK_EXTERNAL_ODOO trigger
  • Configure cron
  • Make trigger Active on the upper right corner
  • Click [Save]
  • Then you can trigger synchronization in some of the following ways:
    1. Click [Run Manually] inside the trigger
    2. Simply wait up to cron job will start on a schedule :)
  • Now open the partner in our Odoo
  • RESULT: avatar is synced from external Odoo
  • You can try to change avatar on external Odoo again and should get the same results

Uploading all existing partners.

  • Open menu [[ Sync Studio ]] >> Sync Projects
  • Select Demo Odoo2odoo Integration project
  • Choose Sync Task Sync Local Partners To Remote Odoo
  • Click button [Run Now]
  • Open the external Odoo
    • RESULT: copies of all our partners are in the external Odoo; they have Sync Studio: prefix (can be configured in project parameter UPLOAD_ALL_PARTNER_PREFIX)

Demo project: GitHub <-> Trello

In this project we create copies of github issues/pull requests and their messages in trello cards. It's one side synchronization: new cards and message in trello are not published in github. Trello and Github labels are synchronized in both directions.

To try it, you need to install this module in demo mode. Also, your odoo instance must be accessible over internet to receive github and trello webhooks.

How it works

Github Webhook Trigger waits from GitHub for issue creation and new messages:

  • if there is no trello card linked to the issue, then create trello card and link it with the issue
  • if new message is posted in github issue, then post message copy in trello card

Github Webhook Trigger waits from GitHub for label attaching/detaching (Trello Webhook Trigger works in the same way)

  • if label is attached in GitHub issue , then check for github label and trello label links and create trello label if there is no such link yet
  • if label is attached in github issue, then attach corresponding label in trello card
  • if label is detached in github issue, then detach corresponding label in trello card

Github Webhook Trigger waits from GitHub for label updating/deleting (Trello Webhook Trigger works in the same way):

  • if label is changed and there is trello label linked to it, then update the label
  • if label is changed and there is trello label linked to it, then delete the label

There is still possibility that labels are mismatch, e.g. due to github api temporary unavailability or misfunction (e.g. api request to add label responded with success, but label was not attached) or if odoo was stopped when github tried to notify about updates. In some cases, we can just retry the handler (e.g. there was an error on api request to github/trello, then the system tries few times to repeat label attaching/detaching). As a solution for cases when retrying didn't help (e.g. api is still not working) or cannot help (e.g. odoo didn't get webhook notification), we run a Cron Trigger at night to check for labels mismatch and synchronize them. In LABELS_MERGE_STRATEGY you can choose which strategy to use:

  • USE_TRELLO -- ignore github labels and override them with trello labels
  • USE_GITHUB -- ignore trello labels and override them with push github labels
  • UNION -- add missed labels from both side
  • INTERSECTION -- remove labels that are not attached on both side

Configuration

  • Open menu [[ Sync Studio ]] >> Sync Projects

  • Select Demo Github-Trello Integration project

  • In Parameters tab set Secrets (check Description and Documentation links near the parameters table about how to get the secret parameters):

    • GITHUB_REPO
    • GITHUB_TOKEN
    • TRELLO_BOARD_ID
    • TRELLO_KEY
    • TRELLO_TOKEN
  • In Available Tasks tab:

    • Click [Edit]
    • Open Labels Conflict resolving task
    • In Available Triggers tab:
      • Open CONFLICT_RESOLVING Cron
      • Change Next Execution Date in webhook to the night time
      • Set Number of Calls, a negative value means no limit (e.g. -1)
      • Make it active on the upper right corner
    • Click [Save]
  • Make integration Active on the upper right corner

  • In project's Manual Triggers tab:

    • Click [Run Now] buttons in trigger SETUP_GITHUB

    • Click [Run Now] buttons in triggers SETUP_TRELLO. Note, that it doesn't work without one of the following workarounds:

      • open file sync/controllers/webhook.py and temporarily change type="json" to type="http". Revert the changes after successfully setting up trello

      • add header "Content-Type: application/json" via your web server. Example for nginx:

        location /website/action-json/ {
            return 200 "{}";
        }
        
    • After a successful SETUP_TRELLO trigger run, return everything to its original position, otherwise the project will not work correctly

Usage

Syncing new Github issue

  • Open Github
  • Create issue
  • Open trello
  • RESULT: you see a copy of the Github issue
  • Go back to the Github issue
  • Post a message
  • Now go back to the trello card
  • RESULT: you see a copy of the message
  • You can also add/remove github issue labels or trello card labels (note that the name of the label must be added in Trello so that there are no errors in the GitHub).
    • RESULT: once you change them on one side, after short time, you will see the changes on another side

Labels syncing

  • Open Github or Trello
  • Rename or delete some label
  • RESULT: the same happened in both systems

Conflict resolving

  • Create a github issue and check that it's syncing to trello
  • Stop Odoo
  • Make different changes of labels both in github issue and trello card
  • Start Odoo
  • Open menu [[ Sync Studio ]] >> Projects
  • Select Demo Trello-Github integration project
  • Click [Edit] and open Labels Conflict Resolving task in Available Tasks tab
  • Make CONFLICT_RESOLVING Cron Trigger run in one of the following ways
    1. Choose Cron Trigger and click [Run Manually]
    2. Change Next Execution Date to a past time and wait up to 1 minute
  • RESULT: the github issue and corresponding trello card the same set of labels. The merging is done according to selected strategy in LABELS_MERGE_STRATEGY parameter.

Syncing all existing Github issues.

  • Open menu [[ Sync Studio ]] >> Projects
  • Select Demo Tello-Github Integration project
  • Click button [Run Now] near to PUSH_ALL_ISSUES manual trigger
  • It will start asynchronous jobs. You can check progress via button Jobs
  • After some time open Trello
    • RESULT: copies of all open github issues are in trello; they have GITHUB: prefix (can be configured in project parameter ISSUE_FROM_GITHUB_PREFIX)

Custom Integration

If you made a custom integration via UI and want to package it into a module, open the Sync Project and click [Actions] -> Export to XML button.

                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007
 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.
  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
  0. Additional Definitions.
  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
  1. Exception to Section 3 of the GNU GPL.
  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
  2. Conveying Modified Versions.
  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or
   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.
  3. Object Code Incorporating Material from Library Header Files.
  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.
   b) Accompany the object code with a copy of the GNU GPL and this license
   document.
  4. Combined Works.
  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.
   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.
   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.
   d) Do one of the following:
       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.
       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.
   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)
  5. Combined Libraries.
  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.
   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.
  6. Revised Versions of the GNU Lesser General Public License.
  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

Please log in to comment on this module

  • The author can leave a single reply to each comment.
  • This section is meant to ask simple questions or leave a rating. Every report of a problem experienced while using the module should be addressed to the author directly (refer to the following point).
  • If you want to start a discussion with the author, please use the developer contact information. They can usually be found in the description.
Please choose a rating from 1 to 5 for this module.