Merge branch 'master' of git://git.assembla.com/fpdboz
This commit is contained in:
commit
eab41b1519
147
packaging/windows/py2exeWalkthroughPython26.txt
Normal file
147
packaging/windows/py2exeWalkthroughPython26.txt
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
PY2EXE walkthrough for Python 2.6 & FPDB 0.20
|
||||||
|
created by Gimick on 22nd June 2010
|
||||||
|
|
||||||
|
|
||||||
|
Step 0 Get a fresh XP installation
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
0.1/ Using XPhome 32bit
|
||||||
|
|
||||||
|
Step 1, Python install
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
1.1/ install the following in sequence (accept all default options) there should be no errors !
|
||||||
|
|
||||||
|
Python 2.6.5 ... http://www.python.org/ftp/python/2.6.5/python-2.6.5.msi
|
||||||
|
pywin 214 ... http://sourceforge.net/projects/pywin32/files/pywin32/Build%20214/pywin32-214.win32-py2.6.exe/download
|
||||||
|
numpy 1.4.1 ... http://sourceforge.net/projects/numpy/files/NumPy/1.4.1/numpy-1.4.1-win32-superpack-python2.6.exe/download
|
||||||
|
matplotlib 0.99.3 ... http://sourceforge.net/projects/matplotlib/files/matplotlib/matplotlib-0.99.3/matplotlib-0.99.3.win32-py2.6.exe/download
|
||||||
|
pygtk 2.16.0 ... http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/2.16/pygtk-2.16.0.win32-py2.6.exe
|
||||||
|
pycairo 1.8.6 ... http://ftp.gnome.org/pub/GNOME/binaries/win32/pycairo/1.8/pycairo-1.8.6.win32-py2.6.exe
|
||||||
|
pyGobject 2.20.0 ... http://ftp.gnome.org/pub/GNOME/binaries/win32/pygobject/2.20/pygobject-2.20.0.win32-py2.6.exe
|
||||||
|
py2exe 0.6.9 ... http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/py2exe-0.6.9.win32-py2.6.exe/download
|
||||||
|
|
||||||
|
|
||||||
|
Step 2 Setup GTK
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
There are quite a few GTK packages needed, and rather than install them individually, I used the official AllinOne from the GTK project.
|
||||||
|
|
||||||
|
2,1/ Create a new folder c:\GTK
|
||||||
|
|
||||||
|
2.2/ Extract the following zip file into c:\GTK
|
||||||
|
|
||||||
|
GTK+ all in one 2.20.0 ... http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.20/gtk+-bundle_2.20.0-20100406_win32.zip
|
||||||
|
|
||||||
|
2.3/ If everything has worked, you should have c:\GTK\bin \etc \lib \src and so on created.
|
||||||
|
|
||||||
|
|
||||||
|
Step 3 Set GTK into the PATH variable
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
The path for GTK isn't set by default, so need to let the o/s know where the GTK stuff is.
|
||||||
|
|
||||||
|
3.1/ Rightclick on mycomputer to show system properties
|
||||||
|
3.2/ select advanced/environment Variables
|
||||||
|
3.3/ in "system variables" NOT "user variables" do the following
|
||||||
|
3.3.1/ create a new item as name: GTK_BASEPATH value: c:\GTK
|
||||||
|
3.3.2/ edit the item "path", press home to get to the first character and insert the following text, (no quotes, including semicolon) %GTK_BASEPATH%\bin;
|
||||||
|
|
||||||
|
3.4/ to check, open command prompt and do:
|
||||||
|
|
||||||
|
dos>path ... system should respond with ... PATH=c:\GTK\bin;C:\WIN........
|
||||||
|
|
||||||
|
3.5/ Give it a spin to test (hopefully an application will start, if not, something has gone wrong)
|
||||||
|
|
||||||
|
dos> gtk-demo
|
||||||
|
|
||||||
|
Step 4 Get the fpdb GIT tree
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
4.1/ Best to take a copy to work with; following steps will assume that the fpdb folder is on the Desktop
|
||||||
|
|
||||||
|
|
||||||
|
Step 5 Put MSVCP90.dll temporarily into the fpdb folder
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
py2exe will check for MSVCP90.dll. The version installed by python2.6.5runtime is not in the path, so we will put it in place TEMPORARILY. This will/must be removed manually once the exe has been created, as we do not have a licence to redistribute.
|
||||||
|
|
||||||
|
Search for MSVCP90.dll (should be found in C:\WINDOWS\WinSxS\...
|
||||||
|
copy this file TEMPORARILY to the Desktop\fpdb\pyfpdb folder
|
||||||
|
|
||||||
|
Step 6 Run py2exe to generate fpdb.exe
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
6.1/ Run the script to create the fpdb.exe bundle
|
||||||
|
|
||||||
|
dos> cd Desktop\fpdb\pyfpdb
|
||||||
|
dos> c:\python26\python.exe py2exe_setup.py py2exe
|
||||||
|
|
||||||
|
wait a while, watch lots of copying and whatever.
|
||||||
|
|
||||||
|
6.2/ You should next get prompted for the GTK folder.
|
||||||
|
c:\GTK
|
||||||
|
|
||||||
|
6.3/ If there are no errors reported, it has probably worked, we will test soon.
|
||||||
|
|
||||||
|
Step 7 Delete C++runtime
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This is really really important, this file must NOT be distributed, so get rid of it now to avoid issues.
|
||||||
|
|
||||||
|
7.1/ in Desktop\fpdb\pyfpdb\ remove the file msvcp90.dll
|
||||||
|
|
||||||
|
Step 8 Drag out the completed bundle
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
py2exe creates a new folder for the created software bundle, drag this out to the desktop for ease of working
|
||||||
|
|
||||||
|
8.1/ Drag Desktop\fpdb\pyfpdb\fpdb-yyyymmdd-exe to Desktop\
|
||||||
|
|
||||||
|
|
||||||
|
Step 9 Initial run
|
||||||
|
------------------
|
||||||
|
|
||||||
|
9.1/ Open the Desktop\fpdb-yyyymmdd-exe folder
|
||||||
|
9.2/ In explorer...tools...folder options...View uncheck "Hide extensions for known file types"
|
||||||
|
9.3/ Double click run_fpdb.bat
|
||||||
|
9.4/ check the contents of pyfpdb\fpdb.exe.log, deal with any errors thrown
|
||||||
|
|
||||||
|
Step 10 drum roll.......
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
10.1/ hopefully, fpdb will run
|
||||||
|
10.2/ Try out a few options, deal with any errors reported
|
||||||
|
|
||||||
|
Observe that the msvcp90.dll was provided by the python runtime package, so we don't have to install the separate package from Microsoft. End-users will, however need the dependency.
|
||||||
|
|
||||||
|
Step 11 pruning
|
||||||
|
---------------
|
||||||
|
|
||||||
|
11.1/ The generated folder is 100+MB and can be pruned by removing the following directories:
|
||||||
|
|
||||||
|
pyfpdb/lib/glib-2.0
|
||||||
|
pyfpdb/lib/gtk-2.0/include
|
||||||
|
pyfpdb/lib/pkgconfig
|
||||||
|
pyfpdb/share/aclocal
|
||||||
|
pyfpdb/share/doc
|
||||||
|
pyfpdb/share/glib-2.0
|
||||||
|
pyfpdb/share/gtk-2.0
|
||||||
|
pyfpdb/share/gtk-doc
|
||||||
|
pyfpdb/share/locale
|
||||||
|
pyfpdb/share/man
|
||||||
|
|
||||||
|
Step 12 rename folder
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
12/ Rename the folder to something meaningful to the community
|
||||||
|
|
||||||
|
Step 13 Compress to executable archive
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
13.1/ Download and install 7zip 914 ... http://sourceforge.net/projects/sevenzip/files/7-Zip/9.14/7z914.exe/download
|
||||||
|
13.2/ Rightclick on fpdb executable folder, select 7zip Add to archive... select SFX archive option switch
|
||||||
|
13.3/ Test the created exe file
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,11 @@ import Configuration
|
||||||
|
|
||||||
class GuiPrefs:
|
class GuiPrefs:
|
||||||
|
|
||||||
def __init__(self, config, mainwin, dia):
|
def __init__(self, config, mainwin, dia, parentwin):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.main_window = mainwin
|
self.main_window = mainwin
|
||||||
self.dialog = dia
|
self.dialog = dia
|
||||||
|
self.parent_window = parentwin #need to pass reference of parent, to set transient
|
||||||
|
|
||||||
self.tree_box = gtk.ScrolledWindow()
|
self.tree_box = gtk.ScrolledWindow()
|
||||||
self.tree_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
self.tree_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||||
|
@ -120,7 +121,7 @@ class GuiPrefs:
|
||||||
name = tmodel.get_value( iter, 1 )
|
name = tmodel.get_value( iter, 1 )
|
||||||
val = tmodel.get_value( iter, 2 )
|
val = tmodel.get_value( iter, 2 )
|
||||||
dia_edit = gtk.Dialog(name,
|
dia_edit = gtk.Dialog(name,
|
||||||
self.main_window,
|
self.parent_window,
|
||||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||||
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
|
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
|
||||||
|
@ -162,7 +163,8 @@ if __name__=="__main__":
|
||||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||||
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
|
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
|
||||||
dia.set_default_size(700, 500)
|
dia.set_default_size(700, 500)
|
||||||
prefs = GuiPrefs(config, win, dia.vbox)
|
pw=dia #pass parent window
|
||||||
|
prefs = GuiPrefs(config, win, dia.vbox,pw)
|
||||||
response = dia.run()
|
response = dia.run()
|
||||||
if response == gtk.RESPONSE_ACCEPT:
|
if response == gtk.RESPONSE_ACCEPT:
|
||||||
# save updated config
|
# save updated config
|
||||||
|
|
|
@ -114,7 +114,7 @@ import Database
|
||||||
import Configuration
|
import Configuration
|
||||||
import Exceptions
|
import Exceptions
|
||||||
|
|
||||||
VERSION = "0.20"
|
VERSION = "0.20-pre1"
|
||||||
|
|
||||||
|
|
||||||
class fpdb:
|
class fpdb:
|
||||||
|
@ -279,7 +279,7 @@ class fpdb:
|
||||||
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
|
gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
|
||||||
dia.set_default_size(700, 500)
|
dia.set_default_size(700, 500)
|
||||||
|
|
||||||
prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox)
|
prefs = GuiPrefs.GuiPrefs(self.config, self.window, dia.vbox, dia)
|
||||||
response = dia.run()
|
response = dia.run()
|
||||||
if response == gtk.RESPONSE_ACCEPT:
|
if response == gtk.RESPONSE_ACCEPT:
|
||||||
# save updated config
|
# save updated config
|
||||||
|
@ -287,11 +287,13 @@ class fpdb:
|
||||||
if len(self.nb_tab_names) == 1:
|
if len(self.nb_tab_names) == 1:
|
||||||
# only main tab open, reload profile
|
# only main tab open, reload profile
|
||||||
self.load_profile()
|
self.load_profile()
|
||||||
|
dia.destroy()
|
||||||
else:
|
else:
|
||||||
|
dia.destroy() # destroy prefs before raising warning, otherwise parent is dia rather than self.window
|
||||||
self.warning_box("Updated preferences have not been loaded because "
|
self.warning_box("Updated preferences have not been loaded because "
|
||||||
+ "windows are open. Re-start fpdb to load them.")
|
+ "windows are open. Re-start fpdb to load them.")
|
||||||
|
else:
|
||||||
dia.destroy()
|
dia.destroy()
|
||||||
|
|
||||||
def dia_maintain_dbs(self, widget, data=None):
|
def dia_maintain_dbs(self, widget, data=None):
|
||||||
self.warning_box("Unimplemented: Maintain Databases")
|
self.warning_box("Unimplemented: Maintain Databases")
|
||||||
|
@ -397,11 +399,13 @@ class fpdb:
|
||||||
if self.obtain_global_lock(): # returns true if successful
|
if self.obtain_global_lock(): # returns true if successful
|
||||||
|
|
||||||
#lock_released = False
|
#lock_released = False
|
||||||
dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
|
dia_confirm = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_WARNING,
|
||||||
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
|
buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables")
|
||||||
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \
|
diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \
|
||||||
+self.db.database+" on "+self.db.host+" they will be deleted."
|
+self.db.database+" on "+self.db.host+" they will be deleted."
|
||||||
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
|
dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted
|
||||||
|
# disable windowclose, do not want the the underlying processing interrupted mid-process
|
||||||
|
dia_confirm.set_deletable(False)
|
||||||
|
|
||||||
response = dia_confirm.run()
|
response = dia_confirm.run()
|
||||||
dia_confirm.destroy()
|
dia_confirm.destroy()
|
||||||
|
@ -417,7 +421,7 @@ class fpdb:
|
||||||
# for other dbs use same connection as holds global lock
|
# for other dbs use same connection as holds global lock
|
||||||
# self.fdb_lock.fdb.recreate_tables()
|
# self.fdb_lock.fdb.recreate_tables()
|
||||||
# TODO: figure out why this seems to be necessary
|
# TODO: figure out why this seems to be necessary
|
||||||
dia_restart = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING,
|
dia_restart = gtk.MessageDialog(parent=self.window, flags=0, type=gtk.MESSAGE_WARNING,
|
||||||
buttons=(gtk.BUTTONS_OK), message_format="Restart fpdb")
|
buttons=(gtk.BUTTONS_OK), message_format="Restart fpdb")
|
||||||
diastring = "You should now restart fpdb."
|
diastring = "You should now restart fpdb."
|
||||||
dia_restart.format_secondary_text(diastring)
|
dia_restart.format_secondary_text(diastring)
|
||||||
|
@ -431,9 +435,11 @@ class fpdb:
|
||||||
|
|
||||||
def dia_recreate_hudcache(self, widget, data=None):
|
def dia_recreate_hudcache(self, widget, data=None):
|
||||||
if self.obtain_global_lock():
|
if self.obtain_global_lock():
|
||||||
self.dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache")
|
self.dia_confirm = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache")
|
||||||
diastring = "Please confirm that you want to re-create the HUD cache."
|
diastring = "Please confirm that you want to re-create the HUD cache."
|
||||||
self.dia_confirm.format_secondary_text(diastring)
|
self.dia_confirm.format_secondary_text(diastring)
|
||||||
|
# disable windowclose, do not want the the underlying processing interrupted mid-process
|
||||||
|
self.dia_confirm.set_deletable(False)
|
||||||
|
|
||||||
hb1 = gtk.HBox(True, 1)
|
hb1 = gtk.HBox(True, 1)
|
||||||
self.h_start_date = gtk.Entry(max=12)
|
self.h_start_date = gtk.Entry(max=12)
|
||||||
|
@ -481,16 +487,19 @@ class fpdb:
|
||||||
|
|
||||||
def dia_rebuild_indexes(self, widget, data=None):
|
def dia_rebuild_indexes(self, widget, data=None):
|
||||||
if self.obtain_global_lock():
|
if self.obtain_global_lock():
|
||||||
self.dia_confirm = gtk.MessageDialog(parent=None
|
self.dia_confirm = gtk.MessageDialog(parent=self.window
|
||||||
,flags=0
|
,flags=gtk.DIALOG_DESTROY_WITH_PARENT
|
||||||
,type=gtk.MESSAGE_WARNING
|
,type=gtk.MESSAGE_WARNING
|
||||||
,buttons=(gtk.BUTTONS_YES_NO)
|
,buttons=(gtk.BUTTONS_YES_NO)
|
||||||
,message_format="Confirm rebuilding database indexes")
|
,message_format="Confirm rebuilding database indexes")
|
||||||
diastring = "Please confirm that you want to rebuild the database indexes."
|
diastring = "Please confirm that you want to rebuild the database indexes."
|
||||||
self.dia_confirm.format_secondary_text(diastring)
|
self.dia_confirm.format_secondary_text(diastring)
|
||||||
|
# disable windowclose, do not want the the underlying processing interrupted mid-process
|
||||||
|
self.dia_confirm.set_deletable(False)
|
||||||
|
|
||||||
response = self.dia_confirm.run()
|
response = self.dia_confirm.run()
|
||||||
if response == gtk.RESPONSE_YES:
|
if response == gtk.RESPONSE_YES:
|
||||||
|
#FIXME these progress messages do not seem to work
|
||||||
lbl = gtk.Label(" Rebuilding Indexes ... ")
|
lbl = gtk.Label(" Rebuilding Indexes ... ")
|
||||||
self.dia_confirm.vbox.add(lbl)
|
self.dia_confirm.vbox.add(lbl)
|
||||||
lbl.show()
|
lbl.show()
|
||||||
|
@ -562,8 +571,13 @@ class fpdb:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __calendar_dialog(self, widget, entry):
|
def __calendar_dialog(self, widget, entry):
|
||||||
self.dia_confirm.set_modal(False)
|
# do not alter the modality of the parent
|
||||||
|
# self.dia_confirm.set_modal(False)
|
||||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||||
|
d.set_transient_for(self.dia_confirm)
|
||||||
|
d.set_destroy_with_parent(True)
|
||||||
|
d.set_modal(True)
|
||||||
|
|
||||||
d.set_title('Pick a date')
|
d.set_title('Pick a date')
|
||||||
|
|
||||||
vb = gtk.VBox()
|
vb = gtk.VBox()
|
||||||
|
@ -976,9 +990,15 @@ This program is licensed under the AGPL3, see agpl-3.0.txt in the fpdb installat
|
||||||
menuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
|
menuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
|
||||||
menuItem.connect('activate', self.dia_about)
|
menuItem.connect('activate', self.dia_about)
|
||||||
self.statusMenu.append(menuItem)
|
self.statusMenu.append(menuItem)
|
||||||
menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
|
|
||||||
menuItem.connect('activate', self.quit)
|
# do not allow quit - if any transient (popup) windows are open (rebuild cache, rebuild index etc)
|
||||||
self.statusMenu.append(menuItem)
|
# quit from the tray causes a very very unclean shutdown, lockup of python process and failure to release global lock.
|
||||||
|
# fpdb window must be re-opened and the windows closed to quit
|
||||||
|
|
||||||
|
# menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
|
||||||
|
# menuItem.connect('activate', self.quit)
|
||||||
|
# self.statusMenu.append(menuItem)
|
||||||
|
|
||||||
self.statusIcon.connect('popup-menu', self.statusicon_menu, self.statusMenu)
|
self.statusIcon.connect('popup-menu', self.statusicon_menu, self.statusMenu)
|
||||||
self.statusIcon.set_visible(True)
|
self.statusIcon.set_visible(True)
|
||||||
|
|
||||||
|
@ -1025,7 +1045,7 @@ This program is licensed under the AGPL3, see agpl-3.0.txt in the fpdb installat
|
||||||
self.window.present()
|
self.window.present()
|
||||||
|
|
||||||
def info_box(self, str1, str2):
|
def info_box(self, str1, str2):
|
||||||
diapath = gtk.MessageDialog( parent=None, flags=0, type=gtk.MESSAGE_INFO
|
diapath = gtk.MessageDialog( parent=self.window, flags=0, type=gtk.MESSAGE_INFO
|
||||||
, buttons=(gtk.BUTTONS_OK), message_format=str1 )
|
, buttons=(gtk.BUTTONS_OK), message_format=str1 )
|
||||||
diapath.format_secondary_text(str2)
|
diapath.format_secondary_text(str2)
|
||||||
response = diapath.run()
|
response = diapath.run()
|
||||||
|
@ -1033,7 +1053,7 @@ This program is licensed under the AGPL3, see agpl-3.0.txt in the fpdb installat
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def warning_box(self, str, diatitle="FPDB WARNING"):
|
def warning_box(self, str, diatitle="FPDB WARNING"):
|
||||||
diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
diaWarning = gtk.Dialog(title=diatitle, parent=self.window, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
||||||
|
|
||||||
label = gtk.Label(str)
|
label = gtk.Label(str)
|
||||||
diaWarning.vbox.add(label)
|
diaWarning.vbox.add(label)
|
||||||
|
|
|
@ -135,7 +135,7 @@ setup(
|
||||||
|
|
||||||
options = {'py2exe': {
|
options = {'py2exe': {
|
||||||
'packages' : ['encodings', 'matplotlib'],
|
'packages' : ['encodings', 'matplotlib'],
|
||||||
'includes' : ['cairo', 'pango', 'pangocairo', 'atk', 'gobject'
|
'includes' : ['gio', 'cairo', 'pango', 'pangocairo', 'atk', 'gobject'
|
||||||
,'matplotlib.numerix.random_array'
|
,'matplotlib.numerix.random_array'
|
||||||
,'AbsoluteToFpdb', 'BetfairToFpdb'
|
,'AbsoluteToFpdb', 'BetfairToFpdb'
|
||||||
,'CarbonToFpdb', 'EverleafToFpdb'
|
,'CarbonToFpdb', 'EverleafToFpdb'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user