Documentation for Bauble 1.0¶
Bauble is an application for managing botanical specimen collections. With it you can create a searchable database of plant records.
It is open and free and is released under the GNU Public License
Statements¶
Highlights¶
not-so-brief list of highlights, meant to whet your appetite.
taxonomic information¶
When you first start Bauble, and connect to a database, Bauble will initialize the database not only with all tables it needs to run, but it will also populate the taxon tables for ranks family and genus, using the data from the “RBG Kew’s Family and Genera list from Vascular Plant Families and Genera compiled by R. K. Brummitt and published by the Royal Botanic Gardens, Kew in 1992”. In 2015 we have reviewed the data regarding the Orchidaceae, using “Tropicos, botanical information system at the Missouri Botanical Garden - www.tropicos.org” as a source.
importing data¶
Bauble will let you import any data you put in an intermediate json format. What you import will complete what you already have in the database. If you need help, you can ask some Bauble professional to help you transform your data into Bauble’s intermediate json format.
synonyms¶
Bauble will allow you define synonyms for species, genera, families. Also this information can be represented in its intermediate json format and be imported in an existing Bauble database.
scientific responsible¶
Bauble implements the concept of ‘accession’, intermediate between physical plant (or a group thereof) and abstract taxon. Each accession can associate the same plants to different taxa, if two taxonomists do not agree on the identification: each taxonomist can have their say and do not need overwrite each other’s work. All verifications can be found back in the database, with timestamp and signature.
helps off-line identification¶
Bauble allows you associate pictures to physical plants, this can help recognize the plant in case a sticker is lost, or help taxonomic identification if a taxonomist is not available at all times.
exports and reports¶
Bauble will let you export a report in whatever textual format you need. It uses a powerful templating engine named ‘mako’, which will allow you export the data in a selection to whatever format you need. Once installed, a couple of examples are available in the mako subdirectory.
annotate your info¶
You can associate notes to plants, accessions, species, .... Notes can be categorized and used in searches or reports.
garden or herbarium¶
Management of plant locations.
database history¶
All changes in the database is stored in the database, as history log. All changes are ‘signed’ and time-stamped. Bauble makes it easy to retrieve the list of all changes in the last working day or week, or in any specific period in the past.
simple and powerful search¶
Bauble allows you search the database using simple keywords, e.g.: the name of the location or a genus name, or you can write more complex queries, which do not reach the complexity of SQL but allow you a decent level of detail localizing your data.
database agnostic¶
Bauble is not a database management system, so it does not reinvent the wheel. It works storing its data in a SQL database, and it will connect to any database management system which accepts a SQLAlchemy connector. This means any reasonably modern database system and includes MySQL, PostgreSQL, Oracle. It can also work with sqlite, which, for single user purposes is quite sufficient and efficient. If you connect Bauble to a real database system, you can consider making the database part of a LAMP system (Linux-Apache-MySQL-Php) and include your live data on your institution web site.
language agnostic¶
The program was born in English and all its technical and user documentation is still only in that language, but the program itself has been translated and can be used in various other languages, including Spanish (86%), Portuguese (100%), French (42%), to name some Southern American languages, as well as Swedish (100%) and Czech (100%).
platform agnostic¶
Installing Bauble on Windows is an easy and linear process, it will not take longer than 10 minutes. Bauble was born on Linux and installing it on ubuntu, fedora or debian is also rather simple. It has been recently successfully tested on MacOSX 10.9.
easily updated¶
The installation process will produce an updatable installation, where updating it will take less than one minute. Depending on the amount of feedback we receive, we will produce updates every few days or once in a while.
unit tested¶
Bauble is continuously and extensively unit tested, something that makes regression of functionality close to impossible. Every update is automatically quality checked, on the Travis Continuous Integration service. Integration of TravisCI with the github platform will make it difficult for us to release anything which has a single failing unit test.
Most changes and additions we make, come with some extra unit test, which defines the behaviour and will make any undesired change easily visible.
customizable/extensible¶
Bauble is extensible through plugins and can be customized to suit the needs of the institution.
Who is behind Bauble¶
Bauble started as a one-man project, by Brett Adams. He wrote Bauble for the Belize Botanical Garden, and later on adapted it for a couple of other users who asked him to use it. Brett made Bauble a commons, by releasing it under a GPL license.
After some years of stagnation Mario Frasca took responsibility of updating Bauble, and it is now Mario Frasca writing this, enhancing the software, looking for users, requesting feedback...
So currently behind Bauble there’s again one developer, but much more importantly, a small but growing global users community.
Translations are provided by volunteers who mostly stay behind the scenes, translating a couple of missing terms or sentences, and disappearing again.
To make things clearer when we speak of Bauble, but should—and in this document we will—indicate whether it’s Bauble(the software), or Bauble(the people), unless obviously we mean both things.
Mission¶
Mission: the mission is a purpose, it defines the rationale of an entity and is specific and true. For Bauble, the Mission Statement sets out the social order to which Bauble is committed, the needs that are satisfied with Bauble(the software) and with the services of Bauble(the people), the market in which Bauble develops and its intended public image.
- access to software
- access to development
- bundling resources
- open source
- open data
Vision¶
The Vision serves to indicate the way ahead and projects a future image of what we want our organization to be, in a realistic and attractive way. It serves as motivation because it visualizes the challenge and direction of necessary changes in order to grow and prosper.
- by the year 2020
- reference point
- community
- development
- integration with web portal
- geographic information
Installing Bauble¶
Introduction¶
bauble.classic is a cross-platform program and it will run on unix machines like Linux and MacOSX, as well as on Windows.
To install Bauble first requires that you install its dependencies that cannot be installed automatically. These include virtualenvwrapper, PyGTK and pip. Python and GTK+, you probably already have. As long as you have these packages installed then Bauble should be able to install the rest of its dependencies by itself.
Note
If you follow these installation steps, you will end with Bauble running within a Python virtual environment, all Python dependencies installed locally, non conflicting with any other Python program you may have on your system.
if you later choose to remove Bauble, you simply remove the virtual environment, which is a directory, with all of its content.
Installing on Linux¶
Download the devinstall.sh script and run it:
https://raw.githubusercontent.com/Bauble/bauble.classic/master/scripts/devinstall.sh
Please not that the script will not help you install any extra database connector. This you will do in a later step.
You can study the script to see what steps if runs for you. In short it will install dependencies which can’t be satisfied in a virtual environment, then it will create a virtual environment named bacl, download the sources and connect your git checkout to the bauble-1.0 branch (this you can consider a production line), it then builds bauble, downloading all remaining dependencies, and finally it creates a startup script in your ~/bin folder.
If the script ends without error, you can now start bauble:
~/bin/bauble
or update bauble to the latest released production patch:
~/bin/bauble -u
The same script you can use to switch to a different production line, but at the moment there’s only bauble-1.0.
on Unity, open a terminal, start bauble, its icon will show up in the launcher, you can now lock to launcher it.
If you would like to use the default SQLite database or you don’t know what this means then you can skip this step. If you would like to use a database backend other than the default SQLite backend then you will also need to install a database connector.
If you would like to use a PostgreSQL database then activate the virtual environment and install psycopg2 with the following commands:
source ~/.virtualenvs/bacl/bin/activate pip install -U psycopg2
You might need solve dependencies. How to do so, depends on which Linux flavour you are using. Check with your distribution documentation.
Next...
Installing on MacOSX¶
Being MacOSX a unix environment, most things will work the same as on Linux (sort of).
One difficulty is that there are many more versions of MacOSX out there than one would want to support, and only the current and its immediately preceding release are kept up-to-date by Apple-the-firm.
Last time we tested, some of the dependencies could not be installed on MacOSX 10.5 and we assume similar problems would present themselves on older OSX versions. Bauble has been successfully tested with 10.7 and 10.9.
First of all, you need things which are an integral part of a unix environment, but which are missing in a off-the-shelf mac:
- developers tools: xcode. check the wikipedia page for the version supported on your mac.
- package manager: homebrew (tigerbrew for older OSX versions).
with the above installed, run:
brew doctor
make sure you understand the problems it reports, and correct them. pygtk will need xquartz and brew will not solve the dependency automatically. either install xquartz using brew or the way you prefer:
brew install Caskroom/cask/xquartz
then install the remaining dependencies:
brew install git
brew install pygtk # takes time and installs all dependencies
follow all instructions on how to activate what you have installed.
the rest is just as on a normal unix machine, and we have a devinstall.sh script for it. Read the above Linux instructions, follow them, enjoy.
Next...
Installing on Windows¶
The current maintainer of bauble.classic has no interest in learning how to produce Windows installers, so the Windows installation is here reduced to the same installation procedure as on Unix (Linux and MacOSX).
Please report any trouble. Help with packaging will be very welcome, in particular by other Windows users.
The steps described here instruct you on how to install Git, Gtk, Python, and the python database connectors. With this environment correctly set up, the Bauble installation procedure runs as on Linux. The concluding steps are again Windows specific.
Note
Bauble has been tested with and is known to work on W-XP, W-7 and W-8. Although it should work fine on other versions Windows it has not been thoroughly tested.
Note
Direct download links are given for all needed components. They have been tested in September 2015, but things change with time. If any of the direct download links stops working, please ring the bell, so we can update the information here.
The installation steps on Windows:
download and install
git
(comes with a unix-likesh
and includesvi
) from:https://git-scm.com/download/win
all default options are fine, except we need git to be executable from the command prompt:
download and install Python 2.x (32bit) from:
Direct link to download Python
Bauble has been developed and tested using Python 2.x. It will definitely not run on Python 3.x. If you are interested in helping port to Python 3.x, please contact the Bauble maintainers.
when installing Python, do put Python in the PATH:
download
pygtk
from the following source. (this requires 32bit python). be sure you download the “all in one” version:http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/
make a complete install, selecting everything:
(Windows 8.x) please consider this additional step. It is possibly necessary to avoid the following error on Windows 8.1 installations:
Building without Cython. ERROR: 'xslt-config' is not recognized as an internal or external command, operable program or batch file.
If you skip this step and can confirm you get the error, please inform us.
You can download lxml from:
https://pypi.python.org/pypi/lxml/3.4.4
Remember you need the 32 bit version, for Python 2.7.
(optional) download and install a database connector other than
sqlite3
.On Windows, it is NOT easy to install
psycopg2
from sources, using pip, so “avoid the gory details” and use a pre-compiled pagkage from:REBOOT
hey, this is Windows, you need to reboot for changes to take effect!
download and run (from
\system32\cmd.exe
) the batch file:right before you hit the enter key to run the script, your screen might look like something like this:
this will pull the
bauble.classic
repository on github to your home directory, underLocal\github\Bauble
, checkout thebauble-1.0
production line, create a virtual environment and install bauble into it.you can also run
devinstall.bat
passing it as argument the numerical part of the production line you want to follow.this is the last installation step that depends, heavily, on a working internet connection.
the operation can take several minutes to complete, depending on the speed of your internet connection.
the last installation step creates the Bauble group and shortcuts in the Windows Start Menu, for all users. To do so, you need run a script with administrative rights. The script is called
devinstall-finalize.bat
, it is right in your HOME folder, and has been created at the previous step.right-click on it, select run as administrator, confirm you want it to make changes to your computer. These changes are in the Start Menu only: create the Bauble group, place the Bauble shortcut.
download the batch file you will use to stay up-to-date with the production line you chose to follow:
if you are on a recent Bauble installation, each time you start the program, Bauble will check on the development site and alert you of any newer bauble release within your chosen production line.
any time you want to update your installation, just start the command prompt and run
bauble-update.bat
If you would like to generate and print PDF reports using Bauble’s default report generator then you will need to download and install Apache FOP. After extracting the FOP archive you will need to include the directory you extracted to in your PATH.
Next...
Troubleshooting¶
any error related to lxml.
In order to be able to compile lxml, you have to install a C compiler (on Linux this would be the
gcc
package) and Cython (a Python specialization, that gets compiled into C code. Note: Cython is not CPython).However, It should not be necessary to compile anything, and
pip
should be able to locate the binary modules in the online libraries.For some reason, this is not the case on Windows 8.1.
https://pypi.python.org/pypi/lxml/3.4.4
Please report any other trouble related to the installation of lxml.
Couldn’t install gdata.
For some reason the Google’s gdata package lists itself in the Python Package Index but doesn’t work properly with the easy_install command. You can download the latest gdata package from:
http://code.google.com/p/gdata-python-client/downloads/list
Unzip it and run
python setup.py installw
in the folder you unzip it to.
Next...
Using Bauble¶
Getting Started¶
Should you SQLite?¶
Is this the first time you use Bauble, are you going to work in a stand-alone setting, you have not the faintest idea how to manage a database management system? If you answered yes to any of the previous, you probably better stick with SQLite, the easy, fast, zero-administration file-based database.
With SQLite, you do not need any preparation and you can continue with connecting.
On the other hand, if you want to connect more than one bauble workstation to the same database, or if you want to make your data available for other clients, as could be a web server in a LAMP setting, you should consider keeping your database in a database management system like PostgreSQL or MySQL/MariaDB, both supported by Bauble.
When connecting to a database server as one of the above, you have to manually create: at least one bauble user, the database you want bauble to use, and to give at lest one bauble user full permissions on its database. When this is done, Bauble will be able to proceed, creating the tables and importing the default data set. The process is database-dependent and it falls beyond the scope of this manual.
If you already got the chills or sick at your stomach, no need to worry, just stick with SQLite, you do not miss on features nor performance.
Connecting to a database¶
When you start Bauble the first thing that comes up is the connection dialog.
Quite obviously, if this is the first time you start Bauble, you have no connections yet and Bauble will alert you about it.

This alert will show at first activation and also in the future if your connections list becomes empty. As it says: click on Add to create your first connection.

Just insert a name for your connection, something meaningful you associate with the collection to be represented in the database (for example: “my home garden”), and click on OK. You will be back to the previous screen, but your connection name will be selected and the Connection Details will have expanded.

specify the connection details
If you do not know what to do here, Bauble will help you stay safe. Activate the Use default locations check box and create your first connection by clicking on Connect.
You may safely skip the remainder of this section for the time being and continue reading to the following section.
fine-tune the connection details
By default Bauble uses the file-based SQLite database. During the installation process you had the choice (and you still have after installation), to add database connectors other than the default SQLite.
In this example, Bauble can connect to SQLite, PostgreSQL and MySQL, but no connector is available for Oracle or MS SQL Server.

If you use SQLite, all you really need specify is the connection name. If
you let Bauble use the default filename then Bauble creates a database file
with the same name as the connection and .db
extension, and a pictures
folder with the same name and no extension, both in ~/.bauble
on
Linux/MacOSX or in AppData\Roaming\Bauble
on Windows.
Still with SQLite, you might have received or downloaded a bauble database, and you want to connect to it. In this case you do not let Bauble use the default filename, but you browse in your computer to the location where you saved the Bauble SQLite database file.
If you use a different database connector, the dialog box will look different and it will offer you the option to fine tune all parameters needed to connect to the database of your choice.
If you are connecting to an existing database you can continue to Editing and Inserting Data and subsequently Searching in Bauble, otherwise read on to the following section on initializing a database for Bauble.
If you plan to associate pictures to plants, specify also the pictures root folder. The meaning of this is explained in further detail at Pictures in Editing and Inserting Data.
Initialize a database¶
First time you open a connection to a database which had never been seen by Bauble before, Bauble will first display an alert:

immediately followed by a question:

Be careful when manually specifying the connection parameters: the values you have entered may refer to an existing database, not intended for use with Bauble. By letting Bauble initialize a database, the database will be emptied and all of its content be lost.
If you are sure you want to create a database at this connection then select “Yes”. Bauble will then start creating the database tables and importing the default data. This can take a minute or two so while all of the default data is imported into the database so be patient.
Once your database has been created, configured, initialized, you are ready to start Editing and Inserting Data and subsequently Searching in Bauble.
Searching in Bauble¶
Searching allows you to view, browse and create reports from your data. You can perform searches by either entering the queries in the main search entry or by using the Query Builder to create the queries for you. The results of Bauble searches are listed in the main window.
Search Strategies¶
Three are three types of search strategies available in Bauble. Considering the search stragety types available in Bauble, sorted in increasing complexity: you can search by value, expression or query.
Searching by query, the most complex and powerful, is assisted by the Query Builder, described below.
All searches are case insensitive so searching for Maxillaria and maxillaria will return the same results.
Search by Value¶
Search by value is the simplest way to search. You just type in a string and see what matches. Which fields/columns are search for your string depends on how the different plugins are configured. For example, by default the PlantPlugin search the family name, the genus name, the species and infraspecific species names, vernacular names and geography. So if you want to search in the notes field of any of these types then searching by value is not the search you’re looking for.
Examples of searching by value would be: Maxillaria, Acanth, 2008.1234, 2003.2.1
Search string are separated by spaces. For example if you enter the
search string Block 10
then Bauble will search for the strings Block
and 10 and return all the results that match either of these
strings. If you want to search for Block 10 as a while string then you
should quote the string like "Block 10"
.
Search by Expression¶
Searching with expression gives you a little more control over what
you are searching for. It can narrow the search down to a specific
domain. Expression consist of a domain, an operator and a value. For
example the search: gen=Maxillaria
would return all the genera that
match the name Maxillaria. In this case the domain is gen, the
operator is = and the value is Maxillaria.
The search string gen like max%
would return all the genera whose
names start with “Max”. In this case the domain again is gen, the
operator is like, which allows for “fuzzy” searching and the value is
max%. The percent sign is used as a wild card so if you search for
max% then it search for all value that start with max. If you search
for %max it searches for all values that end in max. The string %max%a
would search for all value that contain max and end in a.
For more information about the different search domain and their short-hand aliases, see search-domains .
If expression are invalid they are usually used as search by value
searchs. For example the search string gen=
will execute a search by
value for the string gen and the search string gen like
will search
for the string gen and the string like.
Search by Query¶
Queries allow the most control over searching. With queries you can search across relations, specific columns and join search using boolean operators like AND and OR.
An example of a query would be:
plant where accession.species.genus.family=Fabaceae and location.site="Block 10"
This query would return all the plants whose family are Fabaceae and are located in Block 10.
Searching with queries usually requires some knowledge of the Bauble internals and database table layouts.
A couple of useful examples:
Which locations are in use:
location where plants.id!=0
Which genera are associated to at least one accession:
genus where species.accession.id!=0
Domains¶
The following are the common search domain and the columns they search by default. The default columns are used when searching by value and expression. The queries do not use the default columns.
Domains: | family, fam: Search genus, gen: Search species, sp: Search geography: Search acc: Search plant: Search location, loc: Search |
---|
The Query Builder¶
The Query Builder helps you build complex search queries through a point and click interface. To open the Query Builder click the to the left of the search entry or select
from the menu.The Query Builder composes a query that will be understood by the Query Search Strategy described above. You can use the Query Builder to get a feeling of correct queries before you start typing them by hand, something that you might prefer if you are a fast typer.
After opening the Query Builder you must select a search domain. The search domain will determine the type of data that is returned and the properties that you can search.

The search domain is similar to a table in the database and the properties would be the columns on the table. Often the table/domain and properties/columns are the same but not always.
Once a search domain is selected you can then select a property of the domain to compare values to. The search operator can then be changed for how you want to make the search comparison. Finally you must enter a value to compare to the search property.

If the search property you have selected can only have specific values then a list of possible values will be provided for you to choose from.
If multiple search properties are necessary then clicking on the plus sign will add more search properties. Select And/Or next to the property name choose how the properties will be combined in the search query.
When you are done building your query click OK to perform the search.
Editing and Inserting Data¶
The main way that we add or change information in Bauble is by using the editors. Each basic type of data has its own editor. For example there is a Family editor, a Genus editor, an Accession editor, etc.
To create a new record click on the
menu on the menubar and then select the type of record your would like to create. This will open a new blank editor for the type.To edit an existing record in the database right click on an item in the search results and select
from the popup menu. This will open an editor that will allow you to change the values on the record that you selected.Most types also have children which you can add by right clicking on the parent and selecting “Add ???...” on the context menu. For example, a Family has Genus children: you can add a Genus to a Family by right clicking on a Family and selecting “Add genus”.
Notes¶
Almost all of the editors in Bauble have a Notes tab which should work the same regardless of which editor you are using.
If you enter a web address in a note then the link will show up in the Links box when the item your are editing is selected in the search results.
You can browse the notes for an item in the database using the Notes box at the bottom of the screen. The Notes box will be desensitized if the selected item does not have any notes.
Family¶
The Family editor allows you to add or change a botanical family.
The Family field on the editor will change the name of the family. The Family field is required.
The Qualifier field will change the family qualifier. The value can either be sensu lato, sensu stricto or nothing.
Synonyms allow you to add other families that are synonyms with the family you are currently editing. To add a new synonyms type in a family name in the entry. You must select a family name from the list of completions. Once you have selcted a family name that you want to add as a synonym click on the Add button next to the synonym list and it will add the selected synonym to the list. To remove a synonym select the synonym from the list and click on the Remove button.
To cancel your changes without saving then click on the Cancel button.
To save the family you are working on then click OK.
To save the family you are working on and add a genus to it then click on the Add Genera button.
To add another family when you are finished editing the current one click on the Next button on the bottom. This will save the current family and open a new blank family editor.
Genus¶
The Genus editor allows you to add or change a botanical genus.
The Family field on the genus editor allows you to choose the family for the genus. When you begin type a family name it will show a list of families to choose from. The family name must already exist in the database before you can set it as the family for the genus.
The Genus field allows you to set the genus for this entry.
The Author field allows you to set the name or abbreviation of the author(s) for the genus.
Synonyms allow you to add other genera that are synonyms with the genus you are currently editing. To add a new synonyms type in a genus name in the entry. You must select a genus name from the list of completions. Once you have selcted a genus name that you want to add as a synonym click on the Add button next to the synonym list and it will add the selected synonym to the list. To remove a synonym select the synonym from the list and click on the Remove button.
To cancel your changes without saving then click on the Cancel button.
To save the genus you are working on then click OK.
To save the genus you are working on and add a species to it then click on the Add Species button.
To add another genus when you are finished editing the current one click on the Next button on the bottom. This will save the current genus and open a new blank genus editor.
Species/Taxon¶
For historical reasons called a species, but by this we mean a taxon at rank species or lower. It represents a unique name in the database. The species editor will allow you to construct the name as well as associate metadata with the taxon such as its distribution, synonyms and other information.
The Infraspecific parts in the species editor will allow you to specify the taxon further than at species rank.
To cancel your changes without saving then click on the Cancel button.
To save the species you are working on then click OK.
To save the species you are working on and add an accession to it then click on the Add Accession button.
To add another species when you are finished editing the current one click on the Next button on the bottom. This will save the current species and open a new blank species editor.
Accessions¶
The Accession editor allows us to add an accession to a species. In Bauble an accession represents a group of plants or clones. The accession would refer maybe a group of seed or cuttings from a species. A plant would be an individual from that accesssion, i.e. a specific plant in a specific location.
Plant¶
The Plant editor.
Creating multiple plants¶
You can create multiple Plants by using ranges in the code entry. This is only allowed when creating new plants and it is not possible when editing existing Plants in the database.
For example the range, 3-5 will create plant with code 3,4,5. The range 1,4-7,25 will create plants with codes 1,4,5,6,7,25.
When you enter the range in the plant code entry the entry will turn blue to indicate that you are now creating multiple plants. Any fields that are set while in this mode will be copied to all the plants that are created.
Pictures¶
Just as almost all objects in the Bauble database can have Notes associated to them, Plants can have Pictures: next to the tab for Notes, the Plants editor contains an extra tab called “Pictures”. You can associate as many pictures as you might need to a plant.
When you associate a picture to a plant, the file is copied in the pictures folder, and a miniature (500x500) is generated and copied in the thumbnails folder inside of the pictures folder.
As of Bauble-1.0.41, Pictures are not kept in the database. To ensure pictures are available on all terminals where you have installed and configured Bauble, you can use a file sharing service like Copy or Dropbox. The personal choice of the writer of this document is to use Copy, because it offers much more space and because of its “Fair Storage” policy.
Remember that you have configured the pictures root folder when you specified the details of your database connection. Again, you should make sure that the pictures root folder is shared with your file sharing service of choice.
When a Plant in the current selection is highlighted, its pictures are displayed in the pictures pane, the pane left of the information pane. When an accession in the selection is highlighted, any picture associated to the plants in the highlighted accession are displayed in the pictures pane.
Locations¶
The Location editor
danger zone¶
The location editor contains an initially hidden section named danger zone. The widgets contained in this section allow the user to merge the current location into a different location, letting the user correct spelling mistakes or implement policy changes.
Tagging¶
Tagging is an easy way to give context to an object or create a collection of object that you want to recall later. For example if you want to collect a bunch of plants that you later want to create a report from you can tag them with the string “for that report i was thinking about”. You can then select “for that report i was thinking about” from the tags menu to show you all the objects you tagged.
Tagging can be done two ways. By selecting one or more items in the search results and pressing Ctrl-T or by selecting
from the menu. If you have selected multiple items then only that tags that are common to all the selected items will have a check next to it.Generating reports¶
Using the Mako Report Formatter¶
The Mako report formatter uses the Mako template language for generating reports. More information about Mako and its language can be found at makotemplates.org.
The Mako templating system should already be installed on your computer if Bauble is installed.
Creating reports with Mako is similar in the way that you would create a web page from a template. It is much simpler than the XSL Formatter(see below) and should be relatively easy to create template for anyone with a little but of programming experience.
The template generator will use the same file extension as the template which should indicate the type of output the template with create. For example, to generate an HTML page from your template you should name the template something like report.html. If the template will generate a comma seperated value file you should name the template report.csv.
The template will receive a variable called values which will contain the list of values in the current search.
The type of each value in values will be the same as the search domain used in the search query. For more information on search domains see Domains.
If the query does not have a search domain then the values could all be of a different type and the Mako template should prepared to handle them.
Using the XSL Report Formatter¶
The XSL report formatter requires an XSL to PDF renderer to convert the data to a PDF file. Apache FOP is is a free and open-source XSL->PDF renderer and is recommended.
If using Linux, Apache FOP should be installable using your package
manager. On Debian/Ubuntu it is installable as fop
in Synaptic or
using the following command:
apt-get install fop
Installing Apache FOP on Windows¶
You have two options for installing FOP on Windows. The easiest way is to download the prebuilt ApacheFOP-0.95-1-setup.exe installer.
Alternatively you can download the archive. After extracting the archive you must add the directory you extracted the archive to to your PATH environment variable.
Importing and Exporting Data¶
Although Bauble can be extended through plugins to support alternate import and export formats, by default it can only import and export comma seperated values files or CSV.
There is some support for exporting to the Access for Biological Collections Data it is limited.
There is also limited support for exporting to an XML format that more or less reflects exactly the tables and row of the database.
Exporting ABCD and XML will not be covered here.
Warning
Importing files will most likely destroy any data you have in the database so make sure you have backed up your data.
Importing from CSV¶
In general it is best to only import CSV files into Bauble that were previously exported from Bauble. It is possible to import any CSV file but that is more advanced that this doc will cover.
To import CSV files into Bauble select
from the menu.After clicking OK on the dialog that ask if you are sure you know what you’re doing a file chooser will open. In the file chooser select the files you want to import.
Exporting to CSV¶
To export the Bauble data to CSV select
from the menu.This tool will ask you to select a directory to export the CSV data. All of the tables in Bauble will be exported to files in the format tablename.txt where tablename is the name of the table where the data was exported from.
Importing from JSON¶
This is the way to import data into an existing database, without destroying previous content. A typical example of this functionality would be importing your digital collection into a fresh, just initialized Bauble database. Converting a database into bauble json interchange format is beyond the scope of this manual, please contact one of the authors if you need any further help.
Using the Bauble json interchange format, you can import data which you have exported from a different Bauble installation.
Exporting to JSON¶
This feature is still under development.

when you activate this export tool, you are given the choice to specify what to export. You can use the current selection to limit the span of the export, or you can start at the complete content of a domain, to be chosen among Species, Accession, Plant.
Exporting Species will only export the complete taxonomic information in your database. Accession will export all your accessions plus all the taxonomic information it refers to: unreferred to taxa will not be exported. Plant will export all living plants (some accession might not be included), all referred to locations and taxa.
Managing Users¶
Note
The Bauble users plugin is only available on PostgreSQL based databases.
The Bauble User’s Plugin will allow you to create and manage the permissions of users for your Bauble database.
Creating Users¶
To create a new user...
Permissions¶
Bauble allows read, write and execute permissions.
Administration¶
Database Administration¶
If you are using a real DBMS to hold your botanic data, then you need do something about database administration. While database adnimistration is far beyond the scope of this document, we make our users aware of it.
SQLite¶
SQLite is not what one would consider a real DBMS: each SQLite database is
just in one file. Make safety copies and you will be fine. If you don’t know
where to look for your database files, consider that, per default, bauble
puts its data in the ~/.bauble/
directory.
In Windows it is somewhere in your AppData
directory, most likely in
AppData\Roaming\Bauble
. Do keep in mind that Windows does its best to
hide the AppData
directory structure to normal users.
The fastest way to open it is with the file explorer: type ``%APPDATA%` and hit enter.
MySQL¶
Please refer to the official documentation.
PostgreSQL¶
Please refer to the official documentation. A very thorough discussion of your backup options starts at chapter_24.
Bauble Configuration¶
Bauble uses a configuration file to store values across invocations. This file is associated to a user account and every user will have their own configuration file.
To review the content of the Bauble configuration file, type :prefs
in
the text entry area where you normally type your searches, then hit enter.
You normally do not need tweaking the configuration file, but you can do so with a normal text editor program. Bauble configuration file is at the default location for SQLite databases.
Reporting Errors¶
Should you notice anything unexpected in Bauble’s behaviour, please consider filing an issue on the Bauble development site.
Bauble development site can be accessed via the Help menu.
Bauble Development¶
Downloading the source¶
The Bauble source can be downloaded from our source repository on github.
If you want a particular version of Bauble, we release and maintain versions
into branches. You should git checkout
the branch corresponding to the
version of your choice. Branch names for Bauble versions are of the form
bauble-x.y
, where x.y can be 1.0, for example. Our workflow is to commit
to the master development branch or to a patch branch and to include the
commits into a release branch when ready.
To check out the most recent code from the source repository you will need to install the Git version control system. Git is incuded in all reasonable Linux distributions and can be installed on all current operating systems.
Once you have installed Git you can checkout the latest Bauble code with the following command:
git clone https://github.com/Bauble/bauble.classic.git
For more information about other available code branches go to bauble.classic on github.
Development Workflow¶
production line¶
A bauble production line is a branch. Currently there is only one production line, that is bauble-1.0. In perspective, we will have several one, each in use by one or more gardens.
As long as we have only one production line, I keep working on the master branch, unless I later realize the work is going to take longer than one or two days.
batches of simple issues¶
For issues that can be managed in one or two commits, and as long as there’s no other activity on the repository, work on the master branch, accumulate issue-solving commits, finally merge master into the production line bauble-1.0.
larger issues¶
When facing a single larger issue, create a branch tag, and follow the workflow described at
https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging
in short:
git up
git checkout -b issue-xxxx
git push origin issue-xxxx
work on the new branch. When ready, go to github, merge the branch with master, solve conflicts where necessary, delete the temporary branch.
when ready for publication, merge master into the production line.
Adding missing unit tests¶
If you are interested contributing to development of Bauble, a good way to do so would be by helping us finding and writing the missing unit tests.
A well tested function is one whose behaviour you cannot change without breaking at least one unit test.
We all agree that in theory theory and practice match perfectly and that one first writes the tests, then implements the function. In practice, however, practice does not match theory and we have been writing tests after writing and even publishing the functions.
This section describes the process of adding unit tests for
bauble.plugins.plants.family.remove_callback
.
What to test¶
First of all, open the coverage report index, and choose a file with low coverage.
For this example, run in October 2015, we landed on
bauble.plugins.plants.family
, at 33%.
https://coveralls.io/builds/3741152/source?filename=bauble%2Fplugins%2Fplants%2Ffamily.py
The first two functions which need tests, edit_callback
and
add_genera_callback
, include creation and activation of an object
relying on a custom dialog box. We should really first write unit tests for
that class, then come back here.
The next function, remove_callback
, also activates a couple of dialog
and message boxes, but in the form of invoking a function requesting user
input via yes-no-ok boxes. These functions we can easily replace with a
function mocking the behaviour.
how to test¶
So, having decided what to describe in unit test, we look at the code and we see it needs discriminate a couple of cases:
- parameter correctness
- the list of families has no elements.
- the list of families has more than one element.
- the list of families has exactly one element.
- cascade
- the family has no genera
- the family has one or more genera
- confirm
- the user confirms deletion
- the user does not confirm deletion
- deleting
- all goes well when deleting the family
- there is some error while deleting the family
I decide I will only focus on the cascade and the confirm aspects. Two binary questions: 4 cases.
where to put the tests¶
Locate the test script and choose the class where to put the extra unit tests.
https://coveralls.io/builds/3741152/source?filename=bauble%2Fplugins%2Fplants%2Ftest.py#L273
Note
The FamilyTests
class contains a skipped test, implementing it
will be quite a bit of work because we need rewrite the
FamilyEditorPresenter, separate it from the FamilyEditorView and
reconsider what to do with the FamilyEditor class, which I think
should be removed and replaced with a single function.
writing the tests¶
After the last test in the FamilyTests class, I add the four cases I want to describe, and I make sure they fail, and since I’m lazy, I write the most compact code I know for generating an error:
def test_remove_callback_no_genera_no_confirm(self):
1/0
def test_remove_callback_no_genera_confirm(self):
1/0
def test_remove_callback_with_genera_no_confirm(self):
1/0
def test_remove_callback_with_genera_confirm(self):
1/0
One test, step by step¶
Let’s start with the first test case.
When writing tests, I generally follow the pattern:
- T₀ (initial condition),
- action,
- T₁ (testing the result of the action given the initial conditions)
Note
There’s a reason why unit tests are called unit tests. Please never test two actions in one test.
So let’s describe T₀ for the first test, a database holding a family without genera:
def test_remove_callback_no_genera_no_confirm(self):
f5 = Family(family=u'Arecaceae')
self.session.add(f5)
self.session.flush()
We do not want the function being tested to invoke the interactive
utils.yes_no_dialog
function, we want remove_callback
to invoke a
non-interactive replacement function. We achieve this simply by making
utils.yes_no_dialog
point to a lambda
expression which, like the
original interactive function, accepts one parameter and returns a
boolean. In this case: False
:
def test_remove_callback_no_genera_no_confirm(self):
# T_0
f5 = Family(family=u'Arecaceae')
self.session.add(f5)
self.session.flush()
# action
utils.yes_no_dialog = lambda x: False
from bauble.plugins.plants.family import remove_callback
remove_callback(f5)
Next we test the result.
Well, we don’t just want to test whether or not the object Arecaceae was
deleted, we also should test the value returned by remove_callback
, and
whether yes_no_dialog
and message_details_dialog
were invoked or
not.
A lambda
expression is not enough for this. We do something apparently
more complex, which will make life a lot easier.
Let’s first define a rather generic function:
def mockfunc(msg=None, name=None, caller=None, result=None):
caller.invoked.append((name, msg))
return result
and we grab partial
from the functools
standard module, to partially
apply the above mockfunc
, leaving only msg
unspecified, and use this
partial application, which is a function accepting one parameter and
returning a value, to replace the two functions in utils
. The test
function now looks like this:
def test_remove_callback_no_genera_no_confirm(self):
# T_0
f5 = Family(family=u'Arecaceae')
self.session.add(f5)
self.session.flush()
self.invoked = []
# action
utils.yes_no_dialog = partial(
mockfunc, name='yes_no_dialog', caller=self, result=False)
utils.message_details_dialog = partial(
mockfunc, name='message_details_dialog', caller=self)
from bauble.plugins.plants.family import remove_callback
result = remove_callback([f5])
self.session.flush()
The test section checks that message_details_dialog
was not invoked,
that yes_no_dialog
was invoked, with the correct message parameter, that
Arecaceae is still there:
# effect
self.assertFalse('message_details_dialog' in
[f for (f, m) in self.invoked])
self.assertTrue(('yes_no_dialog', u'Are you sure you want to '
'remove the family <i>Arecaceae</i>?')
in self.invoked)
self.assertEquals(result, None)
q = self.session.query(Family).filter_by(family=u"Arecaceae")
matching = q.all()
self.assertEquals(matching, [f5])
And so on¶
there are two kinds of people, those who complete what they start, and so on
Next test is almost the same, with the difference that the
utils.yes_no_dialog
should return True
(this we achieve by
specifying result=True
in the partial application of the generic
mockfunc
).
With this action, the value returned by remove_callback
should be
True
, and there should be no Arecaceae Family in the database any more:
def test_remove_callback_no_genera_confirm(self):
# T_0
f5 = Family(family=u'Arecaceae')
self.session.add(f5)
self.session.flush()
self.invoked = []
# action
utils.yes_no_dialog = partial(
mockfunc, name='yes_no_dialog', caller=self, result=True)
utils.message_details_dialog = partial(
mockfunc, name='message_details_dialog', caller=self)
from bauble.plugins.plants.family import remove_callback
result = remove_callback([f5])
self.session.flush()
# effect
self.assertFalse('message_details_dialog' in
[f for (f, m) in self.invoked])
self.assertTrue(('yes_no_dialog', u'Are you sure you want to '
'remove the family <i>Arecaceae</i>?')
in self.invoked)
self.assertEquals(result, True)
q = self.session.query(Family).filter_by(family=u"Arecaceae")
matching = q.all()
self.assertEquals(matching, [])
have a look at commit 734f5bb9feffc2f4bd22578fcee1802c8682ca83 for the other two test functions.
Putting all together¶
From time to time you want to activate the test class you’re working at:
nosetests bauble/plugins/plants/test.py:FamilyTests
And at the end of the process you want to update the statistics:
./scripts/update-coverage.sh
Plugins structure¶
Bauble is a framework for handling collections, and is distributed along with a set of plugins making Bauble a botanical collection manager. But Bauble stays a framework and you could in theory remove all plugins we distribute and write your own, or write your own plugins that extend or complete the current Bauble behaviour.
Once you have selected and opened a database connection, you land in the Search window. The Search window is an interaction between two objects: SearchPresenter (SP) and SearchView (SV).
SV is what you see, SP holds the program status and handles the requests you express through SV. Handling these requests affect the content of SV and the program status in SP.
The search results shown in the largest part of SV are rows, objects that are instances of classes registered in a plugin.
Each of these classes must implement an amount of functions in order to properly behave within the Bauble framework. The Bauble framework reserves space to pluggable classes.
SP knows of all registered (plugged in) classes, they are stored in a dictionary, associating a class to its plugin implementation. SV has a slot (a gtk.Box) where you can add elements. At any time, at most only one element in the slot is visible.
A plugin defines one or more plugin classes. A plugin class plays the role of a partial presenter (pP - plugin presenter) as it implement the callbacks needed by the associated partial view fitting in the slot (pV - plugin view), and the MVP pattern is completed by the parent presenter (SP), again acting as model. To summarize and complete:
- SP acts as model,
- the pV partial view is defined in a glade file.
- the callbacks implemented by pP are referenced by the glade file.
- a context menu for the SP row,
- a children property.
when you register a plugin class, the SP:
- adds the pV in the slot and makes it non-visible.
- adds an instance of pP in the registered plugin classes.
- tells the pP that the SP is the model.
- connects all callbacks from pV to pP.
when an element in pV triggers an action in pP, the pP can forward the action to SP and can request SP that it updates the model and refreshes the view.
When the user selects a row in SP, SP hides everything in the pluggable slot and shows only the single pV relative to the type of the selected row, and asks the pP to refresh the pV with whatever is relative to the selected row.
Apart from setting the visibility of the various pV, nothing needs be disabled nor removed: an invisible pV cannot trigger events!
Developer’s Manual¶
helping bauble development¶
Installing Bauble always includes downloading the sources, connected to the github repository. This is so because in our eyes, every user is always potentially also a developer.
If you want to contribute to Bauble, you can do so in quite a few different ways:
- use the software, note the things you don’t like, open issue for each of them. a developer will react.
- if you have an idea of what you miss in the software but can’t quite formalize it into separate issues, you could consider hiring a professional. this is the best way to make sure that something happens quickly on Bauble. do make sure the developer opens issues and publishes their contribution on github.
- translate! any help with translations will be welcome, so please do! you can do this without installing anything on your computer, just using the on-line translation service offered by http://hosted.weblate.org/
- fork the respository, choose an issue, solve it, open a pull request. see the bug solving workflow below.
bug solving workflow¶
normal development workflow¶
- while using the software, you notice a problem, or you get an idea of something that could be better, you think about it good enough in order to have a very clear idea of what it really is, that you noticed. you open an issue and describe the problem. someone might react with hints.
- you open the issues site and choose one you want to tackle.
- assign the issue to yourself, this way you are informing the world that you have the intention to work at it. someone might react with hints.
- optionally fork the repository in your account and preferably create a branch, clearly associated to the issue.
- write unit tests and commit them to your branch (do not commit failing
unit tests to the
master
branch). - write more unit tests (ideally, the tests form the complete description of the feature you are adding or correcting).
- make sure the feature you are adding or correcting is really completely described by the unit tests you wrote.
- make sure your unit tests are atomic, that is, that you test variations on changes along one single variable. do not give complex input to unit tests or tests that do not fit on one screen (25 lines of code).
- write the code that makes your tests succeed.
- update the i18n files (run
./scripts/i18n.sh
). - whenever possible, translate the new strings you put in code or glade files.
- commit your changes.
- push to github.
- open a pull request.
publishing to production¶
- open the pull request page using as base the production line, compared to
master
. - make sure a
bump
commit is included in the differences. - it should be possible to automatically merge the branches.
- create the new pull request, call it as “publish to the production line”.
- you possibly need wait for travis-ci to perform the checks.
- merge the changes.
- tell the world about it: on facebook, the google group, linkedin, ...
closing step¶
- review this workflow. consider this as a guideline, to yourself and to your colleagues. please help make it better and matching the practice.
Extending Bauble with Plugins¶
Nearly everything about Bauble is extensible through plugins. Plugins can create tables, define custom searchs, add menu items, create custom commands and more.
To create a new plugin you must extend the bauble.pluginmgr.Plugin
class.
structure of user interface¶
the user interface is built according to the Model-View-Presenter architectural pattern. The view is described in a glade file and is totally dumb, you do not subclass it because it implements no behaviour and because its appearance is, as said, described elsewhere (the glade file), including the association signal-callbacks. The model simply follows the sqlalchemy practices.
You will subclass the presenter in order to:
- define
widget_to_field_map
, the association from name of view object to name of model attribute, - override
view_accept_buttons
, the list of widget names which, if activated by the user, mean that the view should be closed, - define all needed callbacks,
The presenter should not know of the internal structure of the view,
instead, it should use the view api to set and query the values inserted by
the user. The base class for the presenter, GenericEditorPresenter
defined in bauble.editor
, implements many generic callbacks.
Model and Presenter can be unit tested, not the View.
The Tag
plugin is a good minimal example, even if the TagItemGUI
falls outside this description. Other plugins do not respect the
description.
A good example of Presenter/View pattern (no model) is given by the connection manager.
We use the same architectural pattern for non-database interaction, by setting the presenter also as model. We do this, for example, for the JSON export dialog box.
API Documentation¶
bauble
¶
The top level module for Bauble.
-
bauble.
version
= '1.0.55'¶ str(object=’‘) -> string
Return a nice string representation of the object. If the argument is a string, the return value is the same object.
-
bauble.
gui
= None¶ bauble.gui is the instance
bauble.ui.GUI
-
bauble.
command_handler
(cmd, arg)¶ Call a command handler.
Parameters: - cmd (str) – The name of the command to call
- arg (list) – The arg to pass to the command handler
-
bauble.
main
(uri=None)¶ Run the main Bauble application.
Parameters: uri (str) – the URI of the database to connect to. For more information about database URIs see http://www.sqlalchemy.org/docs/05/dbengine.html#create-engine-url-arguments
-
bauble.
main_is_frozen
()¶ Return True if we are running in a py2exe environment, else return False
-
bauble.
quit
()¶ Stop all tasks and quit Bauble.
-
bauble.
save_state
()¶ Save the gui state and preferences.
bauble.db
¶
-
bauble.db.
Session
= None¶ bauble.db.Session is created after the database has been opened with
bauble.db.open()
. bauble.db.Session should be used when you need to do ORM based activities on a bauble database. To create a new Session use::Uncategorizedsession = bauble.db.Session()When you are finished with the session be sure to close the session with
session.close()
. Failure to close sessions can lead to database deadlocks, particularly when using PostgreSQL based databases.
-
bauble.db.
engine
= None¶ A
sqlalchemy.engine.base.Engine
used as the default connection to the database.
-
bauble.db.
Base
= <class 'sqlalchemy.ext.declarative.api.Base'>¶
-
bauble.db.
Base
¶ All tables/mappers in Bauble which use the SQLAlchemy declarative plugin for declaring tables and mappers should derive from this class.
An instance of
sqlalchemy.ext.declarative.Base
-
db.
metadata
= MetaData(bind=None)¶
-
bauble.db.
metadata
¶ The default metadata for all Bauble tables.
An instance of
sqlalchemy.schema.MetaData
-
class
bauble.db.
MapperBase
(classname, bases, dict_)¶ MapperBase adds the id, _created and _last_updated columns to all tables.
In general there is no reason to use this class directly other than to extend it to add more default columns to all the bauble tables.
-
class
bauble.db.
HistoryExtension
¶ Bases:
sqlalchemy.orm.deprecated_interfaces.MapperExtension
HistoryExtension is a
MapperExtension
that is added to all clases that inherit from bauble.db.Base so that all inserts, updates, and deletes made to the mapped objects are recorded in the history table.
-
class
bauble.db.
History
(**kwargs)¶ Bases:
sqlalchemy.ext.declarative.api.Base
The history table records ever changed made to every table that inherits from Base
Table name: history
Columns: - id:
sqlalchemy.types.Integer
A unique identifier.
- table_name:
sqlalchemy.types.String
The name of the table the change was made on.
- table_id:
sqlalchemy.types.Integer
The id in the table of the row that was changed.
- values:
sqlalchemy.types.String
The changed values.
- operation:
sqlalchemy.types.String
The type of change. This is usually one of insert, update or delete.
- user:
sqlalchemy.types.String
The name of the user who made the change.
- timestamp:
sqlalchemy.types.DateTime
When the change was made.
- id:
-
bauble.db.
open
(uri, verify=True, show_error_dialogs=False)¶ Open a database connection. This function sets bauble.db.engine to the opened engined.
Return bauble.db.engine if successful else returns None and bauble.db.engine remains unchanged.
Parameters: - uri (str) – The URI of the database to open.
- verify (bool) – Where the database we connect to should be verified as one created by Bauble. This flag is used mostly for testing.
- show_error_dialogs (bool) – A flag to indicate whether the error dialogs should be displayed. This is used mostly for testing.
-
bauble.db.
create
(import_defaults=True)¶ Create new Bauble database at the current connection
Parameters: import_defaults (bool) – A flag that is passed to each plugins install() method to indicate where it should import its default data. This is mainly used for testing. The default value is True
-
bauble.db.
verify_connection
(engine, show_error_dialogs=False)¶ Test whether a connection to an engine is a valid Bauble database. This method will raise an error for the first problem it finds with the database.
Parameters: - engine (
sqlalchemy.engine.Engine
) – the engine to test - show_error_dialogs (bool) – flag for whether or not to show message dialogs detailing the error, default=False
- engine (
bauble.connmgr
¶
bauble.editor
¶
bauble.i18n
¶
The i18n module defines the _() function for creating translatable strings.
_() is added to the Python builtins so there is no reason to import
this module more than once in an application. It is usually imported
in bauble
bauble.ui
¶
bauble.meta
¶
-
bauble.meta.
get_default
(name, default=None, session=None)¶ Get a BaubleMeta object with name. If the default value is not None then a BaubleMeta object is returned with name and the default value given.
If a session instance is passed (session != None) then we don’t commit the session.
-
class
bauble.meta.
BaubleMeta
(**kwargs)¶ Bases:
sqlalchemy.ext.declarative.api.Base
The BaubleMeta class is used to set and retrieve meta information based on key/name values from the bauble meta table.
Table name: bauble
Columns: - name:
The name of the data.
- value:
The value.
bauble.paths
¶
Access to standard paths used by Bauble.
-
bauble.paths.
main_dir
()¶ Returns the path of the bauble executable.
-
bauble.paths.
lib_dir
()¶ Returns the path of the bauble module.
-
bauble.paths.
locale_dir
()¶ Returns the root path of the locale files
-
bauble.paths.
user_dir
()¶ Returns the path to where Bauble settings should be saved.
bauble.pluginmgr
¶
Manage plugin registry, loading, initialization and installation. The plugin manager should be started in the following order:
1. load the plugins: search the plugin directory for plugins, populates the plugins dict (happens in load())
2. install the plugins if not in the registry, add properly installed plugins in to the registry (happens in load())
- initialize the plugins (happens in init())
-
bauble.pluginmgr.
register_command
(handler)¶ Register command handlers. If a command is a duplicate then it will overwrite the old command of the same name.
Parameters: handler – A class which extends pluginmgr.CommandHandler
-
bauble.pluginmgr.
load
(path=None)¶ Search the plugin path for modules that provide a plugin. If path is a directory then search the directory for plugins. If path is None then use the default plugins path, bauble.plugins.
This method populates the pluginmgr.plugins dict and imports the plugins but doesn’t do any plugin initialization.
Parameters: path (str) – the path where to look for the plugins
-
bauble.pluginmgr.
init
(force=False)¶ Initialize the plugin manager.
1. Check for and install any plugins in the plugins dict that aren’t in the registry. 2. Call each init() for each plugin the registry in order of dependency 3. Register the command handlers in the plugin’s commands[]
NOTE: This is called after after Bauble has created the GUI and established a connection to a database with db.open()
-
bauble.pluginmgr.
install
(plugins_to_install, import_defaults=True, force=False)¶ Parameters: - plugins_to_install – A list of plugins to install. If the string “all” is passed then install all plugins listed in the bauble.pluginmgr.plugins dict that aren’t already listed in the plugin registry.
- import_defaults (bool) – Flag passed to the plugin’s install() method to indicate whether it should import its default data.
- force (book) – Force, don’t ask questions.
-
class
bauble.pluginmgr.
Plugin
¶ - tools:
- a list of BaubleTool classes that this plugin provides, the tools’ category and label will be used in Bauble’s “Tool” menu
- depends:
- a list of names classes that inherit from BaublePlugin that this plugin depends on
- cmds:
- a map of commands this plugin handled with callbacks, e.g dict(‘cmd’, lambda x: handler)
- description:
- a short description of the plugin
-
classmethod
init
()¶ init() is run when Bauble is first started
-
classmethod
install
(import_defaults=True)¶ install() is run when a new plugin is installed, it is usually only run once for the lifetime of the plugin
-
class
bauble.pluginmgr.
Tool
¶
-
class
bauble.pluginmgr.
View
(*args, **kwargs)¶
-
class
bauble.pluginmgr.
CommandHandler
¶
bauble.prefs
¶
bauble.task
¶
The bauble.task module allows you to queue up long running tasks. The running tasks still block but allows the GUI to update.
-
bauble.task.
queue
(task)¶ Run a task.
task should be a generator with side effects. it does not matter what it yields, it is important that it does stop from time to time yielding whatever it wants to, and causing the side effect it has to cause.
-
bauble.task.
set_message
(msg)¶ A convenience function for setting a message on the statusbar. Returns the message id
-
bauble.task.
clear_messages
()¶ Clear all the messages from the statusbar that were set with
bauble.task.set_message()
bauble.types
¶
-
class
bauble.btypes.
Enum
(values, empty_to_none=False, strict=True, translations={}, **kwargs)¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
A database independent Enum type. The value is stored in the database as a Unicode string.
-
class
bauble.btypes.
Date
(*args, **kwargs)¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
A Date type that allows Date strings
-
class
bauble.btypes.
DateTime
(*args, **kwargs)¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
A DateTime type that allows strings
bauble.utils
¶
A common set of utility functions used throughout Bauble.
-
bauble.utils.
find_dependent_tables
(table, metadata=None)¶ Return an iterator with all tables that depend on table. The tables are returned in the order that they depend on each other. For example you know that table[0] does not depend on tables[1].
Parameters: - table – The tables who dependencies we want to find
- metadata – The
sqlalchemy.engine.MetaData
object that holds the tables to search through. If None then use bauble.db.metadata
-
bauble.utils.
tree_model_has
(tree, value)¶ Return True or False if value is in the tree.
-
bauble.utils.
search_tree_model
(parent, data, cmp=<function <lambda>>)¶ Return a iterable of gtk.TreeIter instances to all occurences of data in model
Parameters: - parent – a gtk.TreeModel or a gtk.TreeModelRow instance
- data – the data to look for
- cmp – the function to call on each row to check if it matches data, default is C{lambda row, data: row[0] == data}
-
bauble.utils.
clear_model
(obj_with_model)¶ Parameters: obj_with_model – a gtk Widget that has a gtk.TreeModel that can be retrieved with obj_with_mode.get_model Remove the model from the object, deletes all the items in the model, clear the model and then delete the model and set the model on the object to None
-
bauble.utils.
combo_set_active_text
(combo, value)¶ does the same thing as set_combo_from_value but this looks more like a GTK+ method
-
bauble.utils.
set_combo_from_value
(combo, value, cmp=<function <lambda>>)¶ Find value in combo model and set it as active, else raise ValueError cmp(row, value) is the a function to use for comparison
Note
if more than one value is found in the combo then the first one in the list is set
-
bauble.utils.
combo_get_value_iter
(combo, value, cmp=<function <lambda>>)¶ Returns a gtk.TreeIter that points to first matching value in the combo’s model.
Parameters: - combo – the combo where we should search
- value – the value to search for
- cmp – the method to use to compare rows in the combo model and value, the default is C{lambda row, value: row[0] == value}
Note
if more than one value is found in the combo then the first one in the list is returned
-
bauble.utils.
set_widget_value
(widget, value, markup=False, default=None, index=0)¶ Parameters: - widget – an instance of gtk.Widget
- value – the value to put in the widget
- markup – whether or not value is markup
- default – the default value to put in the widget if the value is None
- index – the row index to use for those widgets who use a model
Note
any values passed in for widgets that expect a string will call the values __str__ method
-
bauble.utils.
create_message_dialog
(msg, type=<enum GTK_MESSAGE_INFO of type GtkMessageType>, buttons=<enum GTK_BUTTONS_OK of type GtkButtonsType>, parent=None)¶ Create a message dialog.
Parameters: - msg – The markup to use for the message. The value should be escaped in case it contains any HTML entities.
- type – A GTK message type constant. The default is gtk.MESSAGE_INFO.
- buttons – A GTK buttons type constant. The default is gtk.BUTTONS_OK.
- parent – The parent window for the dialog
Returns a
gtk.MessageDialog
-
bauble.utils.
message_dialog
(msg, type=<enum GTK_MESSAGE_INFO of type GtkMessageType>, buttons=<enum GTK_BUTTONS_OK of type GtkButtonsType>, parent=None)¶ Create a message dialog with
bauble.utils.create_message_dialog()
and run and destroy it.Returns the dialog’s response.
-
bauble.utils.
create_yes_no_dialog
(msg, parent=None)¶ Create a dialog with yes/no buttons.
-
bauble.utils.
yes_no_dialog
(msg, parent=None, yes_delay=-1)¶ Create and run a yes/no dialog.
Return True if the dialog response equals gtk.RESPONSE_YES
Parameters: - msg – the message to display in the dialog
- parent – the dialog’s parent
- yes_delay – the number of seconds before the yes button should become sensitive
-
bauble.utils.
create_message_details_dialog
(msg, details, type=<enum GTK_MESSAGE_INFO of type GtkMessageType>, buttons=<enum GTK_BUTTONS_OK of type GtkButtonsType>, parent=None)¶ Create a message dialog with a details expander.
-
bauble.utils.
message_details_dialog
(msg, details, type=<enum GTK_MESSAGE_INFO of type GtkMessageType>, buttons=<enum GTK_BUTTONS_OK of type GtkButtonsType>, parent=None)¶ Create and run a message dialog with a details expander.
-
bauble.utils.
setup_text_combobox
(combo, values=None, cell_data_func=None)¶ Configure a gtk.ComboBox as a text combobox
NOTE: If you pass a cell_data_func that is a method of an object that holds a reference to combo then the object will not be properly garbage collected. To avoid this problem either don’t pass a method of object or make the method static
Parameters: - combo – gtk.ComboBox
- values – list vales or gtk.ListStore
- cell_date_func –
Associate a button with entry so that when the button is clicked a date is inserted into the entry.
Parameters: - view – a bauble.editor.GenericEditorView
- entry – the entry that the data goes into
- button – the button that enters the data in entry
- date_func – the function that returns a string represention of the date
-
bauble.utils.
to_unicode
(obj, encoding='utf-8')¶ Return obj converted to unicode. If obj is already a unicode object it will not try to decode it to converted it to <encoding> but will just return the original obj
-
bauble.utils.
utf8
(obj)¶ This function is an alias for to_unicode(obj, ‘utf-8’)
-
bauble.utils.
xml_safe
(obj, encoding='utf-8')¶ Return a string with character entities escaped safe for xml, if the str parameter is a string a string is returned, if str is a unicode object then a unicode object is returned
-
bauble.utils.
xml_safe_utf8
(obj)¶ This method is deprecated and just returns xml_safe(obj)
-
bauble.utils.
natsort_key
(obj)¶ a key getter for sort and sorted function
the sorting is done on return value of obj.__str__() so we can sort generic objects as well.
use like: sorted(some_list, key=utils.natsort_key)
-
bauble.utils.
delete_or_expunge
(obj)¶ If the object is in object_session(obj).new then expunge it from the session. If not then session.delete it.
-
bauble.utils.
reset_sequence
(column)¶ If column.sequence is not None or the column is an Integer and column.autoincrement is true then reset the sequence for the next available value for the column...if the column doesn’t have a sequence then do nothing and return
The SQL statements are executed directly from db.engine
This function only works for PostgreSQL database. It does nothing for other database engines.
-
bauble.utils.
make_label_clickable
(label, on_clicked, *args)¶ Parameters: - label – a gtk.Label that has a gtk.EventBox as its parent
- on_clicked – callback to be called when the label is clicked on_clicked(label, event, data)
-
bauble.utils.
enum_values_str
(col)¶ Parameters: col – a string if table.col where col is an enum type return a string with of the values on an enum type join by a comma
-
bauble.utils.
which
(filename, path=None)¶ Return first occurence of file on the path.
-
bauble.utils.
ilike
(col, val, engine=None)¶ Return a cross platform ilike function.
-
bauble.utils.
range_builder
(text)¶ Return a list of numbers from a string range of the form 1-3,4,5
-
bauble.utils.
topological_sort
(items, partial_order)¶ Perform topological sort.
Parameters: - items – a list of items to be sorted.
- partial_order – a list of pairs. If pair (a,b) is in it, it means that item a should appear before item b. Returns a list of the items in one of the possible orders, or None if partial_order contains a loop.
-
bauble.utils.
get_distinct_values
(column, session)¶ Return a list of all the distinct values in a table column
-
bauble.utils.
get_invalid_columns
(obj, ignore_columns=['id'])¶ Return column names on a mapped object that have values which aren’t valid for the model.
Invalid columns meet the following criteria: - nullable columns with null values - ...what else?
-
bauble.utils.
get_urls
(text)¶ Return tuples of http/https links and labels for the links. To label a link prefix it with [label text], e.g. [BBG]http://belizebotanic.org
-
class
bauble.utils.
GenericMessageBox
¶ Bases:
gtk.EventBox
Abstract class for showing a message box at the top of an editor.
-
class
bauble.utils.
MessageBox
(msg=None, details=None)¶ Bases:
bauble.utils.GenericMessageBox
A MessageBox that can display a message label at the top of an editor.
-
class
bauble.utils.
YesNoMessageBox
(msg=None, on_response=None)¶ Bases:
bauble.utils.GenericMessageBox
A message box that can present a Yes or No question to the user
-
bauble.utils.
add_message_box
(parent, type=1)¶ Parameters: - parent – the parent
gtk.Box
width to add the message box to - type – one of MESSAGE_BOX_INFO, MESSAGE_BOX_ERROR or MESSAGE_BOX_YESNO
- parent – the parent
bauble.search
¶
-
class
bauble.search.
SearchParser
¶ The parser for bauble.search.MapperSearch
-
parse_string
(text)¶ request pyparsing object to parse text
text can be either a query, or a domain expression, or a list of values. the self.statement pyparsing object parses the input text and return a pyparsing.ParseResults object that represents the input
-
-
class
bauble.search.
SearchStrategy
¶ Interface for adding search strategies to a view.
-
search
(text, session=None)¶ Parameters: - text – the search string
- session – the session to use for the search
Return an iterator that iterates over mapped classes retrieved from the search.
-
-
class
bauble.search.
MapperSearch
¶ Bases:
bauble.search.SearchStrategy
Mapper Search support three types of search expression: 1. value searches: search that are just list of values, e.g. value1, value2, value3, searches all domains and registered columns for values 2. expression searches: searched of the form domain=value, resolves the domain and searches specific columns from the mapping 3. query searchs: searches of the form domain where ident.ident = value, resolve the domain and identifiers and search for value
-
search
(text, session=None)¶ Returns a set() of database hits for the text search string.
If session=None then the session should be closed after the results have been processed or it is possible that some database backends could cause deadlocks.
-
-
class
bauble.search.
QueryBuilder
(parent=None)¶ Bases:
gtk.Dialog