diff options
author | Christoph Reiter <creiter@src.gnome.org> | 2017-12-10 20:38:47 +0100 |
---|---|---|
committer | Christoph Reiter <creiter@src.gnome.org> | 2017-12-11 15:40:08 +0100 |
commit | dfab41d0b66a15c8cf8229f7522160ec6b08a2b8 (patch) | |
tree | 7440200db14a4d3dc424842caa804a65366decf5 | |
parent | 307e64982fdfcc9b505d867c0628e1e0a189cd67 (diff) | |
download | gobject-introspection-dfab41d0b66a15c8cf8229f7522160ec6b08a2b8.tar.gz |
Add sphinx based documentation
Takes the documentation developed at
https://github.com/pygobject/pygobject-docs
and puts into /docs
See https://pygobject.readthedocs.io for how it looks
Now that we move to gitlab we can use webhooks to trigger builds
on readthedocs from gitlab directly and we should also have a nicer
contribution UX.
This also gets rid of most of README/HACKING/INSTALL and moves most
of the information into the documentation. The README is kept short
and only makes clear what pygobject is and points to the online docs
as that should answer all questions.
setup.py now sets the content of README.rst as long_descriptions,
as that is the content shown on PyPI. This makes the page on PyPI
look the same as on gitlab.
https://bugzilla.gnome.org/show_bug.cgi?id=791448
51 files changed, 2933 insertions, 533 deletions
@@ -77,3 +77,5 @@ Makefile.in /dist/ /pygobject.egg-info/ /MANIFEST +/docs/_build +/PyGObject.egg-info/ diff --git a/HACKING b/HACKING deleted file mode 100644 index 4d96e9a6..00000000 --- a/HACKING +++ /dev/null @@ -1,37 +0,0 @@ -Making a release -================ - -1. Make sure configure.ac has the right version number -2. Update NEWS file (use "make release-news" target and then edit as you see fit) -3. Run make distcheck, fix any issues and commit. -4. Upload tarball: scp pygobject-3.X.Y.tar.gz master.gnome.org: -5. Install tarball: ssh master.gnome.org 'ftpadmin install pygobject-3.X.Y.tar.gz' -6. Commit NEWS as "release 3.X.Y" and push -7. Tag with: git tag -s 3.X.Y -m "release 3.X.Y" -8. Push tag with: git push origin 3.X.Y -9. Commit post-release version bump to configure.ac -10. Send release announcements to gnome-announce-list@gnome.org; pygtk@daa.com.au; python-hackers-list@gnome.org; python-announce-list@python.org -11. blog about it (include the HTMLized NEWS that "make release-news" prints) - -Based on http://live.gnome.org/MaintainersCorner/Releasing - -Branching -========= - -Each cycle after the feature freeze, we create a stable branch so development can continue in the master branch unaffected by the freezes. - -1. Create the branch locally with: git checkout -b pygobject-3-2 -2. Push new branch: git push origin pygobject-3-2 -3. In master, update configure.ac to what will be the next version number (3.3.0) -4. Announce the branching, send email telling people to continue development in master and cherry-picking the changes that are appropriate for the stable branch - -Tests -===== - -'make check' execute all tests -'make check TEST_NAMES="test_gi"' executes the tests in test_gi.py -'make check TEST_NAMES="test_gi.TestUtf8"' executes the tests in test_gi.TestUtf8 -'make check TEST_NAMES="test_gi.TestUtf8.test_utf8_full_return"' executes the test_gi.TestUtf8.test_utf8_full_return test -'make check.gdb' executes all the tests in a gdb session -'make check.valgrind' executes all the tests in valgrind -'make check.quality' executes pyflakes and pep8 tests diff --git a/INSTALL b/INSTALL deleted file mode 100644 index d60e29ab..00000000 --- a/INSTALL +++ /dev/null @@ -1,370 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation, -Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell commands './configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the 'README' file for -instructions specific to this package. Some packages provide this -'INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The 'configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a 'Makefile' in each directory of the package. -It may also create one or more '.h' files containing system-dependent -definitions. Finally, it creates a shell script 'config.status' that -you can run in the future to recreate the current configuration, and a -file 'config.log' containing compiler output (useful mainly for -debugging 'configure'). - - It can also use an optional file (typically called 'config.cache' -and enabled with '--cache-file=config.cache' or simply '-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how 'configure' could check whether to do them, and mail -diffs or instructions to the address given in the 'README' so they can -be considered for the next release. If you are using the cache, and at -some point 'config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file 'configure.ac' (or 'configure.in') is used to create -'configure' by a program called 'autoconf'. You need 'configure.ac' if -you want to change it or regenerate 'configure' using a newer version -of 'autoconf'. - - The simplest way to compile this package is: - - 1. 'cd' to the directory containing the package's source code and type - './configure' to configure the package for your system. - - Running 'configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type 'make' to compile the package. - - 3. Optionally, type 'make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type 'make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the 'make install' phase executed with root - privileges. - - 5. Optionally, type 'make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior 'make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing 'make clean'. To also remove the - files that 'configure' created (so you can compile the package for - a different kind of computer), type 'make distclean'. There is - also a 'make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type 'make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like 'make install' and 'make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the 'configure' script does not know about. Run './configure --help' -for details on some of the pertinent environment variables. - - You can give 'configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU 'make'. 'cd' to the -directory where you want the object files and executables to go and run -the 'configure' script. 'configure' automatically checks for the -source code in the directory that 'configure' is in and in '..'. This -is known as a "VPATH" build. - - With a non-GNU 'make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use 'make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple '-arch' options to the -compiler but only a single '-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the 'lipo' tool if you have problems. - -Installation Names -================== - - By default, 'make install' installs the package's commands under -'/usr/local/bin', include files under '/usr/local/include', etc. You -can specify an installation prefix other than '/usr/local' by giving -'configure' the option '--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option '--exec-prefix=PREFIX' to 'configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like '--bindir=DIR' to specify different values for particular -kinds of files. Run 'configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of '${prefix}', so that -specifying just '--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to 'configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -'make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -'${prefix}'. Any directories that were specified during 'configure', -but not in terms of '${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the 'DESTDIR' variable. For -example, 'make install DESTDIR=/alternate/directory' will prepend -'/alternate/directory' before all installation names. The approach of -'DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of '${prefix}' -at 'configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving 'configure' the -option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. - - Some packages pay attention to '--enable-FEATURE' options to -'configure', where FEATURE indicates an optional part of the package. -They may also pay attention to '--with-PACKAGE' options, where PACKAGE -is something like 'gnu-as' or 'x' (for the X Window System). The -'README' should mention any '--enable-' and '--with-' options that the -package recognizes. - - For packages that use the X Window System, 'configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the 'configure' options '--x-includes=DIR' and -'--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of 'make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with 'make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with 'make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - HP-UX 'make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as 'configure' are involved. Use GNU 'make' -instead. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its '<wchar.h>' header file. The option '-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put '/usr/ucb' early in your 'PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in '/usr/bin'. So, if you need '/usr/ucb' -in your 'PATH', put it _after_ '/usr/bin'. - - On Haiku, software installed for all users goes in '/boot/common', -not '/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features 'configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, 'configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -'--build=TYPE' option. TYPE can either be a short name for the system -type, such as 'sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file 'config.sub' for the possible values of each field. If -'config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option '--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with '--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for 'configure' scripts to share, -you can create a site shell script called 'config.site' that gives -default values for variables like 'CC', 'cache_file', and 'prefix'. -'configure' looks for 'PREFIX/share/config.site' if it exists, then -'PREFIX/etc/config.site' if it exists. Or, you can set the -'CONFIG_SITE' environment variable to the location of the site script. -A warning: not all 'configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to 'configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the 'configure' command line, using 'VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified 'gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for 'CONFIG_SHELL' due to -an Autoconf limitation. Until the limitation is lifted, you can use -this workaround: - - CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash - -'configure' Invocation -====================== - - 'configure' recognizes the following options to control how it -operates. - -'--help' -'-h' - Print a summary of all of the options to 'configure', and exit. - -'--help=short' -'--help=recursive' - Print a summary of the options unique to this package's - 'configure', and exit. The 'short' variant lists options used - only in the top level, while the 'recursive' variant lists options - also present in any nested packages. - -'--version' -'-V' - Print the version of Autoconf used to generate the 'configure' - script, and exit. - -'--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally 'config.cache'. FILE defaults to '/dev/null' to - disable caching. - -'--config-cache' -'-C' - Alias for '--cache-file=config.cache'. - -'--quiet' -'--silent' -'-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to '/dev/null' (any error - messages will still be shown). - -'--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - 'configure' can determine that directory automatically. - -'--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -'--no-create' -'-n' - Run the configure checks, but stop before creating any output - files. - -'configure' also accepts some other, not widely useful, options. Run -'configure --help' for more details. diff --git a/MANIFEST.in b/MANIFEST.in index b9f067e9..72a28137 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,9 +2,7 @@ include *.am include autogen.sh include configure.ac include COPYING -include HACKING include *.in -include INSTALL include m4/introspection.m4 include m4/python.m4 include NEWS @@ -15,3 +13,4 @@ recursive-include examples *.py *.am *.png *.css *.ui *.gif *.gresource *.jpg *. recursive-include gi *.am *.h recursive-include pygtkcompat *.am recursive-include tests *.py *.c *.h *.xml *.supp *nouppera *.am +recursive-include docs *.rst *.svg LICENSE *.ico *.png *.css *.py *.dia Makefile diff --git a/Makefile.am b/Makefile.am index 643aefc7..c097d9d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,10 +22,10 @@ EXTRA_DIST = \ m4/introspection.m4 \ setup.py \ MANIFEST.in \ - README.rst + README.rst \ + docs MAINTAINERCLEANFILES = \ - $(srcdir)/INSTALL \ $(srcdir)/aclocal.m4 \ $(srcdir)/autoscan.log \ $(srcdir)/compile \ @@ -143,6 +143,7 @@ dist-hook: $(BUILT_EXTRA_DIST) for f in $$files; do \ if test -f $$f; then d=.; else d=$(srcdir); fi; \ rm -f $(distdir)/$$f && cp $$d/$$f $(distdir) || exit 1; done + rm -rf "$(distdir)/docs/_build" # pycheck_subdirs = @@ -1,126 +1,21 @@ -========= -PyGObject -========= +.. image:: https://pygobject.readthedocs.io/en/latest/_images/pygobject.svg + :align: center + :width: 400px + :height: 98px -This archive contains bindings for the GLib, and GObject, -to be used in Python. It is a fairly complete set of bindings, -it's already rather useful, and is usable to write moderately -complex programs. (see the examples directory for some examples -of the simpler programs you could write). +| -If you have any enhancements or bug reports, please file them in -bugzilla at: +**PyGObject** is a Python package which provides bindings for `GObject +<https://developer.gnome.org/gobject/stable/>`__ based libraries such as `GTK+ +<https://www.gtk.org/>`__, `GStreamer <https://gstreamer.freedesktop.org/>`__, +`WebKitGTK+ <https://webkitgtk.org/>`__, `GLib +<https://developer.gnome.org/glib/stable/>`__, `GIO +<https://developer.gnome.org/gio/stable/>`__ and many more. - http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject +It supports Linux, Windows and macOS and works with **Python 2.7+** as well as +**Python 3.4+**. PyGObject, including this documentation, is licensed under +the **LGPLv2.1+**. -If you have a patch, file the bug first and then use the "create new -attachment" link on the bug's info page. My preferred format for -patches is unified diff format (ie. diff -u). Please don't send me -diffs which don't have any context, as these make it very difficult to -see what the patch does. +---- - -New Versions -============ - -New versions of this package can be found at: - - http://ftp.gnome.org/pub/GNOME/sources/pygobject/ - - -Mailing list -============ - -pygobject development is discussed on the GNOME python-hackers mailing list. -You can subscribe to it through the web interface: - - https://mail.gnome.org/mailman/listinfo/python-hackers-list/ - - -Requirements -============ - - * C compiler (GCC and MSVC supported) - * Python 2.7 or higher - * Glib/Gio 2.38.0 or higher - * gobject-introspection 1.46.0 or higher - * libffi (optional) - - -Copyright Information -===================== - -This software is covered by the GNU Lesser General Public Licence -(version 2.1, or if you choose, a later version). Basically just don't -say you wrote bits you didn't. - - -Compilation -=========== - -PyGObject uses the standard autotools for the build infrastructure. To -build, it should be as simple as running:: - - $ ./configure --prefix=<prefix where python is installed> - $ make - $ make install - -By default, configure searches for a few well-known Python interpreter -names, such as "python3", "python2", "python2.7", or "python". If your -Python interpreter isn't in the path, or is not called "python", you can -configure pygobject to build against that with --with-python=<path> or -setting the PYTHON environment variable:: - - $ ./configure --with-python=python3 - $ PYTHON=python3.2 ./configure - $ ./configure --with-python=~/my-patched-python/python - -If configure can't find GTK+, you may need to set the PKG_CONFIG_PATH -environment variable to help it find the libraries. - -The "make install" target will generate normal and optimised bytecode -for all the .py files. - -Note. If you're installing to another prefix than the one where python -is installed you'll need to set the PYTHONPATH variable to the -$prefix/lib/pythonX.Y/site-packages directory created by -the PyGObject installation. - - -Tests -===== - -After having compiled and installed pygobject, you may want to test them. -There are a number of example programs available in the examples/ -subdirectory. - - -Getting Help -============ - -If you have questions about programming with PyGObject, you might want to -check the documentation on - - https://live.gnome.org/PyGObject/ - -If that does not help, send a message to the mailing list (information on -subscribing is above), or join #python on irc.gnome.org. - - -Authors -======= - -Original authors: - * James Henstridge <james@daa.com.au> - * Johan Dahlin <johan@gnome.org> - -Current maintainers: - * Tomeu Vizoso <tomeu.vizoso@collabora.co.uk> - * Martin Pitt <martinpitt@gnome.org> - * Paolo Borelli <pborelli@gnome.org> - * Ignacio Casal Quinteiro <icq@gnome.org> - * Sebastian Pölsterl <sebp@k-d-w.org> - * Simon Feltman <sfeltman@gnome.org> - * Christoph Reiter <reiter.christoph@gmail.com> - -See the NEWS file and the git history for a list of all contributors. +For more information visit https://pygobject.readthedocs.io diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..7b132252 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,16 @@ +DIAS = $(wildcard images/*.dia) +DIA_SVGS = $(patsubst %.dia,%.svg,$(DIAS)) + +all: _build + +images/%.svg: images/%.dia + dia $< --export=$@ --filter=dia-svg + +_build: Makefile *.rst devguide/*.rst guide/*.rst conf.py images/*.png $(DIA_SVGS) ../README.rst + sphinx-build -b html . _build + +linkcheck: + sphinx-build -b linkcheck -n . _build + +clean: + rm -R _build diff --git a/docs/changelog.rst b/docs/changelog.rst new file mode 100644 index 00000000..2c4f6b12 --- /dev/null +++ b/docs/changelog.rst @@ -0,0 +1,10 @@ +Changelog +========= + +Versions with an odd minor version are unstable releases (e.g. 3.27.x) while +versions with even minor version are stable releases (e.g. 3.28.x) + +For more details see the GIT log: https://git.gnome.org//browse/pygobject/log + +.. include:: ../NEWS + :code: diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..aff0fff9 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +extensions = [ + 'sphinx.ext.todo', + 'sphinx.ext.intersphinx', + 'sphinx.ext.extlinks', +] + +intersphinx_mapping = { + 'gtk': ('https://lazka.github.io/pgi-docs/Gtk-3.0', None), + 'gobject': ('https://lazka.github.io/pgi-docs/GObject-2.0', None), + 'glib': ('https://lazka.github.io/pgi-docs/GLib-2.0', None), + 'gdk': ('https://lazka.github.io/pgi-docs/Gdk-3.0', None), + 'gio': ('https://lazka.github.io/pgi-docs/Gio-2.0', None), + 'python2': ('https://docs.python.org/2.7', None), + 'python3': ('https://docs.python.org/3', None), +} + +source_suffix = '.rst' +master_doc = 'index' +exclude_patterns = ['_build', 'README.rst'] + +pygments_style = 'tango' +html_theme = 'sphinx_rtd_theme' +html_show_copyright = False +html_favicon = "images/favicon.ico" +project = "PyGObject" +html_title = project + +html_context = { + 'extra_css_files': [ + 'https://quodlibet.github.io/fonts/font-mfizz.css', + '_static/extra.css', + ], +} + +html_static_path = [ + "extra.css", + "images/pygobject-small.svg", +] + +html_theme_options = { + "display_version": False, +} + +extlinks = { + 'gnomebug': ('https://bugzilla.gnome.org/show_bug.cgi?id=%s', '#'), +} + +suppress_warnings = ["image.nonlocal_uri"] diff --git a/docs/contact.rst b/docs/contact.rst new file mode 100644 index 00000000..f41de73d --- /dev/null +++ b/docs/contact.rst @@ -0,0 +1,11 @@ +======= +Contact +======= + +**IRC** + #python on irc.gnome.org + + Logs for the channel: https://quodlibet.duckdns.org/irc/pygobject + +**Mailinglist** + https://mail.gnome.org/mailman/listinfo/python-hackers-list diff --git a/docs/devguide/building_testing.rst b/docs/devguide/building_testing.rst new file mode 100644 index 00000000..87f86000 --- /dev/null +++ b/docs/devguide/building_testing.rst @@ -0,0 +1,56 @@ +================== +Building & Testing +================== + +Building with Autotools +----------------------- + +Building for Python 2: + +:: + + ./autogen.sh --with-python=python2 + make + +Building for Python 3: + +:: + + ./autogen.sh --with-python=python3 + make + + +Building with Setuptools +------------------------ + +Building in the source directory: + +:: + + python setup.py buildext --inplace + + +Testing +------- + +To run the test suite:: + + make check + +To test only a specific file/class/function:: + + make check TEST_NAMES=test_gi + make check TEST_NAMES=test_gi.TestUtf8 + make check TEST_NAMES=test_gi.TestUtf8.test_utf8_full_return + +To execute all the tests in a gdb session:: + + make check.gdb + +To executes all the tests in valgrind:: + + make check.valgrind + +To execute pyflakes and pep8 tests:: + + make check.quality diff --git a/docs/devguide/dev_environ.rst b/docs/devguide/dev_environ.rst new file mode 100644 index 00000000..4d3985f3 --- /dev/null +++ b/docs/devguide/dev_environ.rst @@ -0,0 +1,46 @@ +.. include:: ../icons.rst + +================================== +Creating a Development Environment +================================== + +This describes how to work on PyGObject itself. Please follow the instructions +on ":ref:`gettingstarted`" first, as they are a pre-requirement. + + +|ubuntu-logo| Ubuntu / |debian-logo| Debian +------------------------------------------- + +.. code:: console + + sudo apt build-dep pygobject + sudo apt install autoconf-archive + git clone https://git.gnome.org/browse/pygobject + cd pygobject + ./autogen.sh + make + make check + + +|windows-logo| Windows +---------------------- + +.. code:: console + + pacman -S --needed --noconfirm base-devel mingw-w64-i686-toolchain git \ + mingw-w64-i686-python3 mingw-w64-i686-python3-cairo \ + mingw-w64-i686-gobject-introspection mingw-w64-i686-gtk3 \ + mingw-w64-i686-libffi autoconf-archive + git clone https://git.gnome.org/browse/pygobject + cd pygobject + ./autogen.sh + make + make check + + +|macosx-logo| macOS +------------------- + +.. code:: console + + # TODO diff --git a/docs/devguide/index.rst b/docs/devguide/index.rst new file mode 100644 index 00000000..0458edab --- /dev/null +++ b/docs/devguide/index.rst @@ -0,0 +1,13 @@ +================= +Development Guide +================= + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + overview + dev_environ + building_testing + style_guide + override_guidelines diff --git a/docs/devguide/override_guidelines.rst b/docs/devguide/override_guidelines.rst new file mode 100644 index 00000000..9315a69b --- /dev/null +++ b/docs/devguide/override_guidelines.rst @@ -0,0 +1,90 @@ +========================== +Python Override Guidelines +========================== + +This document serves as a guide for developers creating new PyGObject +overrides or modifying existing ones. This document is not intended as hard +rules as there may always be pragmatic exceptions to what is listed here. It +is also a good idea to study the `Zen of Python by Tim Peters +<https://www.python.org/dev/peps/pep-0020/>`__. + +In general, overrides should be minimized and preference should always be +placed on updating the underlying API to be more bindable, adding features to +GI to support the requirement, or adding mechanical features to PyGObject +which can apply generically to all overrides (:gnomebug:`721226` and +:gnomebug:`640812`). + +If a GI feature or more bindable API for a library is in the works, it is a +good idea to avoid the temptation to add temporary short term workarounds in +overrides. The reason is this can creaste unnecessary conflicts when the +bindable API becomes a reality (:gnomebug:`707280`). + +* Minimize class overrides when possible. + + *Reason*: Class overrides incur a load time performance penalty because + they require the classes GType and all of the Python method bindings to be + created. See :gnomebug:`705810` + +* Prefer monkey patching methods on repository classes over inheritance. + + *Reason*: Class overrides add an additional level to the method + resolution order (mro) which has a performance penalty. Since overrides are + designed for specific repository library APIs, monkey patching is + reasonable because it is utilized in a controlled manner by the API + designer (as opposed to monkey patching a third-party library which is more + fragile). + +* Avoid overriding ``__init__`` + *Reason*: Sub-classing the overridden class then becomes challenging and + has the potential to cause bugs (see :gnomebug:`711487` and reasoning + listed in https://wiki.gnome.org/Projects/PyGObject/InitializerDeprecations). + +* Unbindable functions which take variadic arguments are generally ok to add + Python implementations, but keep in mind the prior noted guidelines. A lot + of times adding bindable versions of the functions to the underlying library + which take a list is acceptable. For example: :gnomebug:`706119`. Another + problem here is if an override is added, then later a bindable version of + the API is added which takes a list, there is a good chance we have to live + with the override forever which masks a working version implemented by GI. + +* Avoid side effects beyond the intended repositories API in function/method + overrides. + + *Reason*: This conflates the original API and adds a documentation burden + on the override maintainer. + +* Don't change function signatures from the original API and don't add default + values. + + *Reason*: This turns into a documentation discrepancy between the libraries + API and the Python version of the API. Default value work should focus on + bug :gnomebug:`558620`, not cherry-picking individual Python functions and + adding defaults. + +* Avoid implicit side effects to the Python standard library (or anywhere). + + * Don't modify or use sys.argv + + *Reason*: sys.argv should only be explicitly controlled by application + developers. Otherwise it requires hacks to work around a module modifying + or using the developers command line args which they rightfully own. + + .. code:: python + + saved_argv = sys.argv.copy() + sys.argv = [] + from gi.repository import Gtk + sys.argv = saved_argv + + * Never set Pythons default encoding. + + *Reason*: Read or watch Ned Batchelders "`Pragmatic Unicode + <https://nedbatchelder.com/text/unipain.html>`__" + +* For PyGTK compatibility APIs, add them to PyGTKCompat not overrides. +* Prefer adapter patterns over of inheritance and overrides. + + *Reason*: An adapter allows more flexibility and less dependency on + overrides. It allows application developers to use the raw GI API without + having to think about if a particular typelibs overrides have been installed + or not. diff --git a/docs/devguide/overview.rst b/docs/devguide/overview.rst new file mode 100644 index 00000000..28527b61 --- /dev/null +++ b/docs/devguide/overview.rst @@ -0,0 +1,32 @@ +======== +Overview +======== + + +Bug Tracker +----------- + +You can search through the GNOME Bugzilla for existing bug reports: +https://bugzilla.gnome.org/page.cgi?id=browse.html&product=pygobject + +You can also file a new bug report: +https://bugzilla.gnome.org/enter_bug.cgi?product=pygobject + + +Git Repos +--------- + +PyGObject itself is hosted at https://git.gnome.org/browse/pygobject/ + +In addition a GitHub organization exists which contains various related +projects: https://github.com/pygobject + + +Continuous Testing +------------------ + +The test suite gets regularly run on all supported platforms using +https://github.com/pygobject/pygobject-ci + +There is currently no integration with bugzilla/git.gnome.org for this and the +status has to be checked manually. diff --git a/docs/devguide/style_guide.rst b/docs/devguide/style_guide.rst new file mode 100644 index 00000000..0cd01fdd --- /dev/null +++ b/docs/devguide/style_guide.rst @@ -0,0 +1,101 @@ +================ +Style Guidelines +================ + +Python Code +----------- + +* Generally follow Python's `PEP8 + <https://www.python.org/dev/peps/pep-0008/>`__ style guidelines. We run the + pep8 command to verify this during unittest runs. + +* Break up logical blocks of related code with a newline. Specifically add a + blank newline after conditional or looping blocks. +* Don't comment what is obvious. Instead prefer meaningful names of functions + and variables: + + .. code:: python + + # Get the functions signal annotations <-- this comment is unnecessary + return_type, arg_types = get_signal_annotations(func) + +* Use comments to explain non-obvious blocks and conditionals, magic, + workarounds (with bug references), or generally complex pieces of code. + Good examples: + + .. code:: python + + # If a property was defined with a decorator, it may already have + # a name; if it was defined with an assignment (prop = Property(...)) + # we set the property's name to the member name + if not prop.name: + prop.name = name + + .. code:: python + + # Python causes MRO's to be calculated starting with the lowest + # base class and working towards the descendant, storing the result + # in __mro__ at each point. Therefore at this point we know that + # we already have our base class MRO's available to us, there is + # no need for us to (re)calculate them. + if hasattr(base, '__mro__'): + bases_of_subclasses += [list(base.__mro__)] + + +Python Doc Strings +------------------ + +* Doc strings should generally follow + `PEP257 <https://www.python.org/dev/peps/pep-0257/>`__ unless noted here. +* Use `reStructuredText (resST) <http://sphinx-doc.org/rest.html>`__ + annotations. +* Use three double quotes for doc strings (``"""``). +* Use a brief description on the same line as the triple quote. +* Include function parameter documentation (including types, returns, and + raises) between the brief description and the full description. Use a + newline with indentation for the parameters descriptions. + + .. code:: python + + def spam(amount): + """Creates a Spam object with the given amount. + + :param int amount: + The amount of spam. + :returns: + A new Spam instance with the given amount set. + :rtype: Spam + :raises ValueError: + If amount is not a numeric type. + + More complete description. + """ + +* For class documentation, use the classes doc string for an explanation of + what the class is used for and how it works, including Python examples. + Include ``__init__`` argument documentation after the brief description in + the classes doc string. The class ``__init__`` should generally be the first + method defined in a class putting it as close as possible (location wise) to + the class documentation. + + .. code:: python + + class Bacon(CookedFood): + """Bacon is a breakfast food. + + :param CookingType cooking_type: + Enum for the type of cooking to use. + :param float cooking_time: + Amount of time used to cook the Bacon in minutes. + + Use Bacon in combination with other breakfast foods for + a complete breakfast. For example, combine Bacon with + other items in a list to make a breakfast: + + .. code-block:: python + + breakfast = [Bacon(), Spam(), Spam(), Eggs()] + + """ + def __init__(self, cooking_type=CookingType.BAKE, cooking_time=15.0): + super(Bacon, self).__init__(cooking_type, cooking_time) diff --git a/docs/extra.css b/docs/extra.css new file mode 100644 index 00000000..3ae7bdbb --- /dev/null +++ b/docs/extra.css @@ -0,0 +1,57 @@ +.wy-side-nav-search { + background-color: initial; +} + +.wy-nav-top { + background-color: #171A2F; +} + +.wy-side-nav-search input[type="text"] { + border-color: transparent; +} + +.wy-nav-content { + margin: initial; +} + +.wy-nav-side { + background-color: #171A2F; +} + +.rst-content div[role=navigation], footer { + font-size: 0.85em; + color: #999; +} + +.rst-content div[role=navigation] hr { + margin-top: 6px; +} + +footer hr { + margin-bottom: 6px; +} + +.rst-footer-buttons { + display: none; +} + +a.icon-home, a.icon-home:hover { + display: inline-block; + padding: 4px 4px 4px 21px; + background: transparent url(pygobject-small.svg) center left no-repeat; + background-size: 1.2em; + margin-top: 0.2em; + margin-bottom: 1em; +} + + +.fa-home::before, .icon-home::before { + content: ""; +} + +.wy-nav-top a { + margin: -2em; + background: transparent url(pygobject-small.svg) center left no-repeat; + background-size: 1.2em; + padding: 4px 4px 4px 24px; +} diff --git a/docs/further.rst b/docs/further.rst new file mode 100644 index 00000000..832cf45e --- /dev/null +++ b/docs/further.rst @@ -0,0 +1,10 @@ +================= +Further Resources +================= + +`Python GTK+ 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.io>`__ + Many examples showing how to build an application using PyGObject and GTK+. + +`Python GI API Reference <https://lazka.github.io/pgi-docs>`__ + Auto generated API documentation for many libraries accessible through + PyGObject. diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 00000000..c6e95b2b --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,128 @@ +.. include:: icons.rst + +.. _gettingstarted: + +=============== +Getting Started +=============== + +To get things started we will try to run a very simple `GTK+ +<https://www.gtk.org/>`_ based GUI application using the :doc:`PyGObject <index>` provided +Python bindings. First create a small Python script called ``hello.py`` with +the following content and save it somewhere: + +.. code:: python + + import gi + gi.require_version("Gtk", "3.0") + from gi.repository import Gtk + + window = Gtk.Window(title="Hello World") + window.show() + window.connect("destroy", Gtk.main_quit) + Gtk.main() + +Before we can run the example application we need to install PyGObject, GTK+ +and their dependencies. Follow the instructions for your platform below. + +======================================= ==================================== ==================================== ========================================== +|ubuntu-logo| :ref:`Ubuntu <ubuntu>` |fedora-logo| :ref:`Fedora <fedora>` |arch-logo| :ref:`Arch Linux <arch>` |opensuse-logo| :ref:`openSUSE <opensuse>` +|windows-logo| :ref:`Windows <windows>` |macosx-logo| :ref:`macOS <macosx>` |python-logo| :ref:`PyPI <pypi>` +======================================= ==================================== ==================================== ========================================== + + +.. _windows: + +|windows-logo| Windows +---------------------- + +1) Go to http://www.msys2.org/ and download the x86_64 installer +2) Follow the instructions on the page for setting up the basic environment +3) Run ``C:\msys64\mingw32.exe`` - a terminal window should pop up +4) Execute ``pacman -S mingw-w64-i686-gtk3 mingw-w64-i686-python2-gobject mingw-w64-i686-python3-gobject`` +5) To test that GTK+3 is working you can run ``gtk3-demo`` +6) Copy the ``hello.py`` script you created to ``C:\msys64\home\<username>`` +7) In the mingw32 terminal execute ``python2 hello.py`` - a window should appear. + +.. figure:: images/start_windows.png + :scale: 60% + + +.. _ubuntu: + +|ubuntu-logo| Ubuntu / |debian-logo| Debian +------------------------------------------- + +1) Open a terminal +2) Execute ``sudo apt install python-gi python-gi-cairo python3-gi python3-gi-cairo gir1.2-gtk-3.0`` +3) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) +4) Run ``python2 hello.py`` + +.. figure:: images/start_linux.png + :scale: 60% + + +.. _fedora: + +|fedora-logo| Fedora +-------------------- + +1) Open a terminal +2) Execute ``sudo dnf install pygobject3 python3-gobject gtk3`` +3) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) +4) Run ``python2 hello.py`` + + +.. _arch: + +|arch-logo| Arch Linux +---------------------- + +1) Open a terminal +2) Execute ``sudo pacman -S python-gobject python2-gobject gtk3`` +3) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) +4) Run ``python2 hello.py`` + + +.. _opensuse: + +|opensuse-logo| openSUSE +------------------------ + +1) Open a terminal +2) Execute ``sudo zypper install python-gobject python3-gobject gtk3`` +3) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) +4) Run ``python2 hello.py`` + + +.. _macosx: + +|macosx-logo| macOS +------------------- + +1) Go to https://brew.sh/ and install homebrew +2) Open a terminal +3) Execute ``brew install pygobject3 --with-python3 gtk+3`` to install for both python2 and python3 +4) Change the directory to where your ``hello.py`` script can be found (e.g. ``cd Desktop``) +5) Run ``python2 hello.py`` + +.. figure:: images/start_macos.png + :scale: 70% + + +.. _pypi: + +|python-logo| From PyPI +----------------------- + +PyGObject is also available on PyPI: https://pypi.org/project/PyGObject + +For this approach you have to make sure that all runtime and build +dependencies are present yourself as pip will only take care of pycairo. + +.. code:: + + virtualenv --python=python3 myvenv + source myvenv/bin/activate + pip install pygobject + python hello.py diff --git a/docs/guide/api/api.rst b/docs/guide/api/api.rst new file mode 100644 index 00000000..c5e019f0 --- /dev/null +++ b/docs/guide/api/api.rst @@ -0,0 +1,75 @@ +================ +GI Documentation +================ + +This is the API provided by the toplevel "gi" package. + + +.. function:: gi.require_version(namespace, version) + + :param str namespace: The namespace + :param str version: The version of the namespace which should be loaded + :raises: :obj:`ValueError <exceptions.ValueError>` + + Ensures the namespace gets loaded with the given version. If the namespace + was already loaded with a different version or a different version was + required previously raises ValueError. + + :: + + import gi + gi.require_version('Gtk', '3.0') + + +.. function:: gi.require_foreign(namespace, symbol=None) + + :param str namespace: + Introspection namespace of the foreign module (e.g. "cairo") + :param symbol: + Optional symbol typename to ensure a converter exists. + :type symbol: :obj:`str` or :obj:`None` + :raises: :obj:`ImportError <exceptions.ImportError>` + + Ensure the given foreign marshaling module is available and loaded. + + Example: + + .. code-block:: python + + import gi + import cairo + gi.require_foreign('cairo') + gi.require_foreign('cairo', 'Surface') + + +.. function:: gi.check_version(version) + + :param tuple version: A version tuple + :raises: :obj:`ValueError <exceptions.ValueError>` + + Compares the passed in version tuple with the gi version and does nothing + if gi version is the same or newer. Otherwise raises ValueError. + + +.. function:: gi.get_required_version(namespace) + + :returns: The version successfully required previously by :func:`gi.require_version` or :obj:`None` + :rtype: str or :obj:`None` + + +.. data:: gi.version_info + :annotation: = (3, 18, 1) + + The version of PyGObject + + +.. class:: gi.PyGIDeprecationWarning + + The warning class used for deprecations in PyGObject and the included + Python overrides. It inherits from DeprecationWarning and is hidden + by default. + + +.. class:: gi.PyGIWarning + + Like :class:`gi.PyGIDeprecationWarning` but visible by default. diff --git a/docs/guide/api/basic_types.rst b/docs/guide/api/basic_types.rst new file mode 100644 index 00000000..b41fee91 --- /dev/null +++ b/docs/guide/api/basic_types.rst @@ -0,0 +1,53 @@ +=========== +Basic Types +=========== + +PyGObject will automatically convert between C types and Python types. In +cases where it's appropriate it will use default Python types like :obj:`int`, +:obj:`list`, and :obj:`dict`. + + +Number Types +------------ + +All glib integer types get mapped to :obj:`int`, :obj:`long` and :obj:`float`. +Since the glib integer types are always range limited, conversions from Python +int/long can fail with :class:`OverflowError`: + +.. code:: pycon + + >>> GLib.random_int_range(0, 2**31-1) + 1684142898 + >>> GLib.random_int_range(0, 2**31) + Traceback (most recent call last): + File "<stdin>", line 1, in <module> + OverflowError: 2147483648 not in range -2147483648 to 2147483647 + >>> + + +Text Types +---------- + +In case you use Python 2 then text is utf-8 encoded :obj:`str`, in case of +Python 3 :obj:`str` is used. + + +Platform String Types +--------------------- + +* Windows + Python 2: utf-8 encoded :obj:`str` +* Windows + Python 3: :obj:`str` +* Unix + Python 2: :obj:`str` +* Unix + Python 3: :obj:`str` + +On Python 3 there is currently no support for :obj:`bytes`, see `bug 746564 +<https://bugzilla.gnome.org/show_bug.cgi?id=746564>`__ for more details. + + +Other Types +----------- + +* GList <-> :obj:`list` +* GSList <-> :obj:`list` +* GHashTable <-> :obj:`dict` +* arrays <-> :obj:`list` diff --git a/docs/guide/api/flags_enums.rst b/docs/guide/api/flags_enums.rst new file mode 100644 index 00000000..0a90735f --- /dev/null +++ b/docs/guide/api/flags_enums.rst @@ -0,0 +1,39 @@ +============= +Flags & Enums +============= + +Flags are subclasses of :class:`GObject.GFlags` and represent bit fields where +some bits also have names: + +.. code:: pycon + + >>> Gtk.DialogFlags.MODAL + <flags GTK_DIALOG_MODAL of type Gtk.DialogFlags> + >>> Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT + <flags GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT of type Gtk.DialogFlags> + >>> int(_) + 3 + >>> Gtk.DialogFlags(3) + <flags GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT of type Gtk.DialogFlags> + >>> isinstance(Gtk.DialogFlags.MODAL, Gtk.DialogFlags) + True + >>> + +Bitwise operations on them will produce a value of the same type. + + +Enums are subclasses of :class:`GObject.GEnum` and represent a list of named +constants: + +.. code:: pycon + + >>> Gtk.Align.CENTER + <enum GTK_ALIGN_CENTER of type Gtk.Align> + >>> int(Gtk.Align.CENTER) + 3 + >>> int(Gtk.Align.END) + 2 + >>> Gtk.Align(1) + <enum GTK_ALIGN_START of type Gtk.Align> + >>> isinstance(Gtk.Align.CENTER, Gtk.Align) + True diff --git a/docs/guide/api/gobject.rst b/docs/guide/api/gobject.rst new file mode 100644 index 00000000..08c124b9 --- /dev/null +++ b/docs/guide/api/gobject.rst @@ -0,0 +1,91 @@ +============== +GObject.Object +============== + +Compare to other types, :obj:`GObject.Object` has the best integration between +the GObject and Python type system. + +1) It is possible to subclass a :obj:`GObject.Object`. Subclassing + creates a new :obj:`GObject.GType` which is connected to the new Python + type. This means you can use it with API which takes :obj:`GObject.GType`. +2) The Python wrapper instance for a :obj:`GObject.Object` is always the same. + For the same C instance you will always get the same Python instance. + + +In addition :obj:`GObject.Object` has support for :any:`signals <signals>` and +:any:`properties <properties>` + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :hidden: + + signals + properties + + +Examples +-------- + +Subclassing: + +.. code:: pycon + + >>> from gi.repository import GObject + >>> class A(GObject.Object): + ... pass + ... + >>> A() + <__main__.A object at 0x7f9113fc3280 (__main__+A at 0x559d9861acc0)> + >>> A.__gtype__ + <GType __main__+A (94135355573712)> + >>> A.__gtype__.name + '__main__+A' + >>> + +In case you want to specify the GType name we have to provide a +``__gtype_name__``: + +.. code:: pycon + + >>> from gi.repository import GObject + >>> class B(GObject.Object): + ... __gtype_name__ = "MyName" + ... + >>> B.__gtype__ + <GType MyName (94830143629776)> + >>> + +:obj:`GObject.Object` only supports single inheritance, this means you can +only subclass one :obj:`GObject.Object`, but multiple Python classes: + +.. code:: pycon + + >>> from gi.repository import GObject + >>> class MixinA(object): + ... pass + ... + >>> class MixinB(object): + ... pass + ... + >>> class MyClass(GObject.Object, MixinA, MixinB): + ... pass + ... + >>> instance = MyClass() + + +Here we can see how we create a :obj:`Gio.ListStore` for our new subclass and +that we get back the same Python instance we put into it: + +.. code:: pycon + + >>> from gi.repository import GObject, Gio + >>> class A(GObject.Object): + ... pass + ... + >>> store = Gio.ListStore.new(A) + >>> instance = A() + >>> store.append(instance) + >>> store.get_item(0) is instance + True + >>> diff --git a/docs/guide/api/index.rst b/docs/guide/api/index.rst new file mode 100644 index 00000000..efeade31 --- /dev/null +++ b/docs/guide/api/index.rst @@ -0,0 +1,12 @@ +============= +API Reference +============= + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + api + basic_types + flags_enums + gobject diff --git a/docs/guide/api/properties.rst b/docs/guide/api/properties.rst new file mode 100644 index 00000000..0241109e --- /dev/null +++ b/docs/guide/api/properties.rst @@ -0,0 +1,119 @@ +========== +Properties +========== + +Properties are part of a class and are defined through a +:obj:`GObject.ParamSpec`, which contains the type, name, value range and so +on. + +To find all the registered properties of a class you can use the +:meth:`GObject.Object.list_properties` class method. + +.. code:: pycon + + >>> Gio.Application.list_properties() + [<GParamString 'application-id'>, <GParamFlags 'flags'>, <GParamString + 'resource-base-path'>, <GParamBoolean 'is-registered'>, <GParamBoolean + 'is-remote'>, <GParamUInt 'inactivity-timeout'>, <GParamObject + 'action-group'>, <GParamBoolean 'is-busy'>] + >>> param = Gio.Application.list_properties()[0] + >>> param.name + 'application-id' + >>> param.owner_type + <GType GApplication (94881584893168)> + >>> param.value_type + <GType gchararray (64)> + >>> + +The :obj:`GObject.Object` contructor takes multiple properties as keyword +arguments. Property names usually contain "-" for seperating words. In Python +you can either use "-" or "_". In this case variable names don't allow "-", so +we use "_". + +.. code:: pycon + + >>> app = Gio.Application(application_id="foo.bar") + +To get and set the property value see :meth:`GObject.Object.get_property` and +:meth:`GObject.Object.set_property`. + +.. code:: pycon + + >>> app = Gio.Application(application_id="foo.bar") + >>> app + <Gio.Application object at 0x7f7499284fa0 (GApplication at 0x564b571e7c00)> + >>> app.get_property("application_id") + 'foo.bar' + >>> app.set_property("application_id", "a.b") + >>> app.get_property("application-id") + 'a.b' + >>> + + +Each instance also has a ``props`` attribute which exposes all properties +as instance attributes: + +.. code:: pycon + + >>> from gi.repository import Gtk + >>> button = Gtk.Button(label="foo") + >>> button.props.label + 'foo' + >>> button.props.label = "bar" + >>> button.get_label() + 'bar' + >>> + + +To track changes of properties, :obj:`GObject.Object` has a special ``notify`` +signal with the property name as the detail string. Note that in this case you +have to give the real property name and replacing "-" with "_" wont work. + +.. code:: pycon + + >>> app = Gio.Application(application_id="foo.bar") + >>> def my_func(instance, param): + ... print("New value %r" % instance.get_property(param.name)) + ... + >>> app.connect("notify::application-id", my_func) + 11L + >>> app.set_property("application-id", "something.different") + New value 'something.different' + >>> + +You can define your own properties using the :obj:`GObject.Property` decorator, +which can be used similarly to the builtin Python :any:`property` decorator: + +.. function:: GObject.Property(type=None, default=None, nick='', blurb='', \ + flags=GObject.ParamFlags.READWRITE, minimum=None, maximum=None) + + :param GObject.GType type: Either a GType, a type with a GType or a + Python type which maps to a default GType + :param object default: A default value + :param str nick: Property nickname + :param str block: Short description + :param GObject.ParamFlags flags: Property configuration flags + :param object minimum: Minimum value, depends on the type + :param object maximum: Maximum value, depends on the type + + +.. code:: python + + class AnotherObject(GObject.Object): + value = 0 + + @GObject.Property + def prop_pyobj(self): + """Read only property.""" + + return object() + + @GObject.Property(type=int) + def prop_gint(self): + """Read-write integer property.""" + + return self.value + + @prop_gint.setter + def prop_gint(self, value): + self.value = value diff --git a/docs/guide/api/signals.rst b/docs/guide/api/signals.rst new file mode 100644 index 00000000..00018625 --- /dev/null +++ b/docs/guide/api/signals.rst @@ -0,0 +1,93 @@ +======= +Signals +======= + +GObject signals are a system for registering callbacks for specific events. + +To find all signals of a class you can use the +:func:`GObject.signal_list_names` function: + + +.. code:: pycon + + >>> GObject.signal_list_names(Gio.Application) + ('activate', 'startup', 'shutdown', 'open', 'command-line', 'handle-local-options') + >>> + + +To connect to a signal, use :meth:`GObject.Object.connect`: + +.. code:: pycon + + >>> app = Gio.Application() + >>> def on_activate(instance): + ... print("Activated:", instance) + ... + >>> app.connect("activate", on_activate) + 17L + >>> app.run() + ('Activated:', <Gio.Application object at 0x7f1bbb304320 (GApplication at 0x5630f1faf200)>) + 0 + >>> + +It returns number which identifies the connection during its lifetime and which +can be used to modify the connection. + +For example it can be used to temporarily ignore signal emissions using +:meth:`GObject.Object.handler_block`: + +.. code:: pycon + + >>> app = Gio.Application(application_id="foo.bar") + >>> def on_change(*args): + ... print(args) + ... + >>> c = app.connect("notify::application-id", on_change) + >>> app.props.application_id = "foo.bar" + (<Gio.Application object at 0x7f1bbb304550 (GApplication at 0x5630f1faf2b0)>, <GParamString 'application-id'>) + >>> with app.handler_block(c): + ... app.props.application_id = "no.change" + ... + >>> app.props.application_id = "change.again" + (<Gio.Application object at 0x7f1bbb304550 (GApplication at 0x5630f1faf2b0)>, <GParamString 'application-id'>) + >>> + + +You can define your own signals using the :obj:`GObject.Signal` decorator: + + +.. function:: GObject.Signal(name='', flags=GObject.SignalFlags.RUN_FIRST, \ + return_type=None, arg_types=None, accumulator=None, accu_data=None) + + :param str name: The signal name + :param GObject.SignalFlags flags: Signal flags + :param GObject.GType return_type: Return type + :param list arg_types: List of :class:`GObject.GType` argument types + :param GObject.SignalAccumulator accumulator: Accumulator function + :param object accu_data: User data for the accumulator + + +.. code:: python + + class MyClass(GObject.Object): + + @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, return_type=bool, + arg_types=(object,), + accumulator=GObject.signal_accumulator_true_handled) + def test(self, *args): + print("Handler", args) + + @GObject.Signal + def noarg_signal(self): + print("noarg_signal") + + instance = MyClass() + + def test_callback(inst, obj): + print "Handled", inst, obj + return True + + instance.connect("test", test_callback) + instance.emit("test", object()) + + instance.emit("noarg_signal") diff --git a/docs/guide/cairo_integration.rst b/docs/guide/cairo_integration.rst new file mode 100644 index 00000000..84ea3f34 --- /dev/null +++ b/docs/guide/cairo_integration.rst @@ -0,0 +1,39 @@ +================= +Cairo Integration +================= + +Despite `cairo <https://cairographics.org/>`__ not being a GObject based +library, PyGObject provides special cairo integration through `pycairo +<https://pycairo.readthedocs.io>`__. Functions returning and taking cairo data +types get automatically converted to pycairo objects and vice versa. + +Some distros ship the PyGObject cairo support in a separate package. If you've +followed the instructions on ":ref:`gettingstarted`" you should have everything +installed. + +If your application requires the cairo integration you can use +:func:`gi.require_foreign`: + +.. code:: python + + try: + gi.require_foreign("cairo") + except ImportError: + print("No pycairo integration :(") + +Note that PyGObject currently does not support `cairocffi +<https://pypi.python.org/pypi/cairocffi>`__, only pycairo. + + +Demo +---- + +The following example shows a :obj:`Gtk.Window` with a custom drawing in Python +using pycairo. + +.. figure:: images/cairo_integration.png + :scale: 75% + :align: center + +.. literalinclude:: code/cairo-demo.py + :linenos: diff --git a/docs/guide/code/cairo-demo.py b/docs/guide/code/cairo-demo.py new file mode 100755 index 00000000..f5ac1122 --- /dev/null +++ b/docs/guide/code/cairo-demo.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +""" +Based on cairo-demo/X11/cairo-demo.c +""" + +import cairo +import gi +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + +SIZE = 30 + + +def triangle(ctx): + ctx.move_to(SIZE, 0) + ctx.rel_line_to(SIZE, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.close_path() + + +def square(ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2 * SIZE, 0) + ctx.rel_line_to(0, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.close_path() + + +def bowtie(ctx): + ctx.move_to(0, 0) + ctx.rel_line_to(2 * SIZE, 2 * SIZE) + ctx.rel_line_to(-2 * SIZE, 0) + ctx.rel_line_to(2 * SIZE, -2 * SIZE) + ctx.close_path() + + +def inf(ctx): + ctx.move_to(0, SIZE) + ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0) + ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0) + ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, - 2 * SIZE, 0) + ctx.rel_curve_to(-SIZE, -SIZE, - 2 * SIZE, -SIZE, - 2 * SIZE, 0) + ctx.close_path() + + +def draw_shapes(ctx, x, y, fill): + ctx.save() + + ctx.new_path() + ctx.translate(x + SIZE, y + SIZE) + bowtie(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + square(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + triangle(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.new_path() + ctx.translate(3 * SIZE, 0) + inf(ctx) + if fill: + ctx.fill() + else: + ctx.stroke() + + ctx.restore() + + +def fill_shapes(ctx, x, y): + draw_shapes(ctx, x, y, True) + + +def stroke_shapes(ctx, x, y): + draw_shapes(ctx, x, y, False) + + +def draw(da, ctx): + ctx.set_source_rgb(0, 0, 0) + + ctx.set_line_width(SIZE / 4) + ctx.set_tolerance(0.1) + + ctx.set_line_join(cairo.LINE_JOIN_ROUND) + ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0) + stroke_shapes(ctx, 0, 0) + + ctx.set_dash([], 0) + stroke_shapes(ctx, 0, 3 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + stroke_shapes(ctx, 0, 6 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_MITER) + stroke_shapes(ctx, 0, 9 * SIZE) + + fill_shapes(ctx, 0, 12 * SIZE) + + ctx.set_line_join(cairo.LINE_JOIN_BEVEL) + fill_shapes(ctx, 0, 15 * SIZE) + ctx.set_source_rgb(1, 0, 0) + stroke_shapes(ctx, 0, 15 * SIZE) + + +def main(): + win = Gtk.Window() + win.connect('destroy', lambda w: Gtk.main_quit()) + win.set_default_size(450, 550) + + drawingarea = Gtk.DrawingArea() + win.add(drawingarea) + drawingarea.connect('draw', draw) + + win.show_all() + Gtk.main() + + +if __name__ == '__main__': + main() diff --git a/docs/guide/debug_profile.rst b/docs/guide/debug_profile.rst new file mode 100644 index 00000000..628bab17 --- /dev/null +++ b/docs/guide/debug_profile.rst @@ -0,0 +1,112 @@ +===================== +Debugging & Profiling +===================== + +Things can go wrong, these tools may help you find the cause. If you know any +more tricks please share them. + + +GObject Instance Count Leak Check +--------------------------------- + +Requires a development (only available in debug mode) version of glib. Jhbuild +recommended. + +:: + + jhbuild shell + GOBJECT_DEBUG=instance-count GTK_DEBUG=interactive ./quodlibet.py + +* In the GTK+ Inspector switch to the "Statistics" tab +* Sort by "Cumulative" and do the action which you suspect does leak or where + you want to make sure it doesn't repeatedly. Like for example opening + and closing a window or switching between media files to present. +* If something in the "Cumulative" column steadily increases there probably + is a leak. + +cProfile Performance Profiling +------------------------------ + +* https://docs.python.org/2/library/profile.html +* bundled with python + +:: + + python -m cProfile -s [sort_order] quodlibet.py > cprof.txt + + +where ``sort_order`` can one of the following: +calls, cumulative, file, line, module, name, nfl, pcalls, stdname, time + +Example output:: + + 885311 function calls (866204 primitive calls) in 12.110 seconds + + Ordered by: cumulative time + + ncalls tottime percall cumtime percall filename:lineno(function) + 1 0.002 0.002 12.112 12.112 quodlibet.py:11(<module>) + 1 0.007 0.007 12.026 12.026 quodlibet.py:25(main) + 19392/13067 0.151 0.000 4.342 0.000 __init__.py:639(__get__) + 1 0.003 0.003 4.232 4.232 quodlibetwindow.py:121(__init__) + 1 0.000 0.000 4.029 4.029 quodlibetwindow.py:549(select_browser) + 1 0.002 0.002 4.022 4.022 albums.py:346(__init__) + ... + ... + +SnakeViz - cProfile Based Visualization +--------------------------------------- + +* https://jiffyclub.github.io/snakeviz/ +* ``pip install snakeviz`` + +:: + + python -m cProfile -o prof.out quodlibet.py + snakeviz prof.out + + +Sysprof - System-wide Performance Profiler for Linux +---------------------------------------------------- + +* http://sysprof.com/ + +:: + + sysprof-cli -c "python quodlibet/quodlibet.py" + sysprof capture.syscap + +GDB +--- + +:: + + gdb --args python quodlibet/quodlibet.py + # type "run" and hit enter + + +Debugging Wayland Issues +------------------------ + +:: + + mutter --nested --wayland + # start your app, it should show up in the nested mutter + +:: + + weston + # start your app, it should show up in the nested weston + + +Debugging HiDPI Issue +--------------------- + +:: + + GDK_SCALE=2 ./quodlibet/quodlibet.py + +:: + + MUTTER_DEBUG_NUM_DUMMY_MONITORS=2 MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2 mutter --nested --wayland + # start your app, it should show up in the nested mutter diff --git a/docs/guide/deploy.rst b/docs/guide/deploy.rst new file mode 100644 index 00000000..efee20c2 --- /dev/null +++ b/docs/guide/deploy.rst @@ -0,0 +1,52 @@ +.. include:: ../icons.rst + +====================== +Application Deployment +====================== + +There is currently no nice deployment story, but it's not impossible. This is +a list of random notes and examples. + +|linux-logo| Linux +------------------ + +On Linux there is no single strategy. Quod Libet uses distutils, MyPaint uses +SCons. Gramps uses distutils. + +|macosx-logo| macOS +------------------- + +On OSX you can use `gtk-osx <https://git.gnome.org/browse/gtk-osx>`__ which is +based on jhbuild and then `gtk-mac-bundler +<https://git.gnome.org/browse/gtk-mac-bundler>`__ for packaging things up and +making libraries relocatable. With macOS bundles you generally have a startup +shell script which sets all the various env vars relative to the bundle, +similar to jhbuild. + +|windows-logo| Windows +---------------------- + +On Windows things are usually build to be relocatable by default, so no env +vars are needed. You can build/install through MSYS2, copy the bits you need +and you are done. For GUI application you'll also need an exe launcher that +links against the python dll. + +Example Deployments +------------------- + +* `Quod Libet <https://quodlibet.readthedocs.io/>`__ provides a Windows + installer based on MSYS2 and NSIS3. On macOS, jhbuild is used for building, + gtk.mac-bundler for packing things up and `dmgbuild + <https://pypi.python.org/pypi/dmgbuild>`__ for creating a dmg. distutis is + used for building/installing the application into the final environment. + Most of this is automated and scripts can be found in the git repo. + +* `MyPaint <http://mypaint.org/>`__ provides a Windows installer based on + MSYS2 and Inno Setup. It uses SCons for building/installing the application. + +* ...? + +Other options +------------- + +* `PyInstaller <http://www.pyinstaller.org/>`_ is a program that freezes (packages) Python programs into stand-alone executables, under Windows, Linux, Mac OS X, and more. PyInstaller's packager has built-in support for automatically including PyGObject dependencies with your application without requiring additional configuration. diff --git a/docs/guide/faq.rst b/docs/guide/faq.rst new file mode 100644 index 00000000..48031b09 --- /dev/null +++ b/docs/guide/faq.rst @@ -0,0 +1,11 @@ +========================== +Frequently Asked Questions +========================== + +How can I use PyGObject with the official CPython builds on Windows? +-------------------------------------------------------------------- + +https://sourceforge.net/projects/pygobjectwin32 provides binaries which should +be ABI compatible with the official CPython binaries. I'd recommend using +msys2 if at all possible, since there are more people involved and it's easier +to fix/patch things yourself. diff --git a/docs/guide/images/cairo_integration.png b/docs/guide/images/cairo_integration.png Binary files differnew file mode 100644 index 00000000..47268754 --- /dev/null +++ b/docs/guide/images/cairo_integration.png diff --git a/docs/guide/index.rst b/docs/guide/index.rst new file mode 100644 index 00000000..ac966d7e --- /dev/null +++ b/docs/guide/index.rst @@ -0,0 +1,17 @@ +========== +User Guide +========== + + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + api/index + cairo_integration + threading + debug_profile + deploy + testing + porting + faq diff --git a/docs/guide/porting.rst b/docs/guide/porting.rst new file mode 100644 index 00000000..8ee11348 --- /dev/null +++ b/docs/guide/porting.rst @@ -0,0 +1,109 @@ +============================ +Porting from Static Bindings +============================ + +Before PyGObject 3, bindings where not generated automatically through gobject +introspection and where provided as separate Python libraries like pygobject, +pygtk, pygst etc. We call them static bindings. + +If your code contains imports like ``import gtk``, ``import gst``, ``import +glib`` or ``import gobject`` you are using the old bindings and you should +upgrade. + +Note that using old and new bindings in the same process is not supported, you +have to switch everything at once. + + +Static Bindings Library Differences +----------------------------------- + +**pygtk** supported GTK+ 2.0 and Python 2 only. PyGObject supports GTK+ >=3.0 +and Python 2/3. If you port away from pygtk you also have to move to GTK+ 3.0 +at the same time. **pygtkcompat** described below can help you with that +transition. + +**pygst** supports GStreamer 0.10 and Python 2 only. Like with GTK+ you have +to move to PyGObject and GStreamer 1.0 at the same time. + +**pygobject 2** supports glib 2.0 and Python 2. The new bindings also support +glib 2.0 and Python 2/3. + + +General Porting Tips +-------------------- + +PyGObject contains a shell script which can help you with the many naming +differences between static and dynamic bindings: + +https://git.gnome.org/browse/pygobject/plain/tools/pygi-convert.sh + +:: + + ./pygi-convert.sh mymodule.py + +It just does basic text replacement. It reduces the amount of naming changes +you have to make in the beginning, but nothing more. + +1) Run on a Python module +2) Check/Verify the changes made (e.g. using ``git diff``) +3) Finish porting the module by hand +4) Continue to the next module... + + +Porting Tips for GTK+ +--------------------- + +While PyGObject theoretically supports GTK+ 2.0 it is not really usable. It +will be easier to port to GTK+ 3.0 right away. + +For some general advice regarding the migration from GTK+ 2.0 to 3.0 see the +`offical migration guide +<https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html>`__. If you +need to know how a C symbol is exposed in Python have a look at the `symbol +mapping listing <https://lazka.github.io/pgi-docs/#Gtk-3.0/mapping.html>`__. + + +Using the pygtkcompat Compatibility Layer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +PyGObject ships a compatibility layer for pygtk which partially emulates the +old interfaces: + +:: + + from gi import pygtkcompat + pygtkcompat.enable() + pygtkcompat.enable_gtk(version='3.0') + + import gtk + +``enable()`` has to be called once before the first ``gtk`` import. + +Note that pygtkcompat is just for helping you through the transition by +allowing you to port one module at a time. Only a limited subset of the +interfaces are emulated correctly and you should try to get rid of it in the +end. + + +Default Encoding Changes +^^^^^^^^^^^^^^^^^^^^^^^^ + +Importing ``gtk`` had the side effect of changing the default Python encoding +from ASCII to UTF-8 (check ``sys.getdefaultencoding()``) and that no longer +happens with PyGObject. Since text with pygtk is returned as utf-8 encoded +str, your code is likely depending auto-decoding in many places and you can +change it manually by doing: + +:: + + # Python 2 only + import sys + reload(sys) + sys.setdefaultencoding("utf-8") + # see if auto decoding works: + assert '\xc3\xb6' + u'' == u'\xf6' + +While this is not officially supported by Python I don't know of any +downsides. Once you are sure that you explicitly decode in all places or you +move to Python 3 where things are unicode by default you can remove this +again. diff --git a/docs/guide/testing.rst b/docs/guide/testing.rst new file mode 100644 index 00000000..6a7c6632 --- /dev/null +++ b/docs/guide/testing.rst @@ -0,0 +1,39 @@ +.. include:: ../icons.rst + +================================== +Testing and Continuous Integration +================================== + +To get automated tests of GTK+ code running on a headless server use Xvfb +(virtual framebuffer X server). It provides the ``xvfb-run -a`` command which +creates a temporary X server without the need for any real display hardware. + +:: + + xvfb-run -a python my_script.py + + +Continuous Integration using Travis CI / CircleCI +------------------------------------------------- + +Travis CI uses a rather old Ubuntu and thus the supported GTK+ is at 3.10 and +PyGObject is at 3.12. If that's enough for you then have a look at our Travis +CI example project: + + |github-logo| https://github.com/pygobject/pygobject-travis-ci-examples + + .. image:: https://travis-ci.org/pygobject/pygobject-travis-ci-examples.svg?branch=master + :target: https://travis-ci.org/pygobject/pygobject-travis-ci-examples + +To get newer PyGObject, GTK+, etc. working on `Travis CI +<https://travis-ci.org>`__ or `CircleCI <https://circleci.com>`__ you can use +Docker with an image of your choosing. Have a look at our Docker example +project which runs tests on various Debian, Ubuntu and Fedora versions: + + |github-logo| https://github.com/pygobject/pygobject-travis-ci-docker-examples + + .. image:: https://travis-ci.org/pygobject/pygobject-travis-ci-docker-examples.svg?branch=master + :target: https://travis-ci.org/pygobject/pygobject-travis-ci-docker-examples + + .. image:: https://circleci.com/gh/pygobject/pygobject-travis-ci-docker-examples.svg?style=shield + :target: https://circleci.com/gh/pygobject/pygobject-travis-ci-docker-examples diff --git a/docs/guide/threading.rst b/docs/guide/threading.rst new file mode 100644 index 00000000..c1bac32f --- /dev/null +++ b/docs/guide/threading.rst @@ -0,0 +1,290 @@ +===================== +Threads & Concurrency +===================== + +Operations which could potentially block should not be executed in the main +loop. The main loop is in charge of input processing and drawing and +blocking it results in the user interface freezing. For the user this means +not getting any feedback and not being able to pause or abort the operation +which causes the problem. + +Such an operation might be: + +* Loading external resources like an image file on the web +* Searching the local file system +* Writing, reading and copying files +* Calculations where the runtime depends on some external factor + +The following examples show + +* how Python threads, running in parallel to GTK+, can interact with the UI +* how to use and control asynchronous I/O operations in glib + + +Threads +------- + +The first example uses a Python thread to execute code in the background +while still showing feedback on the progress in a window. + +.. code:: python + + import threading + import time + + from gi.repository import GLib, Gtk, GObject + + + def app_main(): + win = Gtk.Window(default_height=50, default_width=300) + win.connect("destroy", Gtk.main_quit) + + progress = Gtk.ProgressBar(show_text=True) + win.add(progress) + + def update_progess(i): + progress.pulse() + progress.set_text(str(i)) + return False + + def example_target(): + for i in range(50): + GLib.idle_add(update_progess, i) + time.sleep(0.2) + + win.show_all() + + thread = threading.Thread(target=example_target) + thread.daemon = True + thread.start() + + + if __name__ == "__main__": + app_main() + Gtk.main() + + +The example shows a simple window containing a progress bar. After everything +is set up it constructs a Python thread, passes it a function to execute, +starts the thread and the GTK+ main loop. After the main loop is started it is +possible to see the window and interact with it. + +In the background ``example_target()`` gets executed and calls +:func:`GLib.idle_add` and :func:`time.sleep` in a loop. In this example +:func:`time.sleep` represents the blocking operation. :func:`GLib.idle_add` +takes the ``update_progess()`` function and arguments that will get passed to +the function and asks the main loop to schedule its execution in the main +thread. This is needed because GTK+ isn't thread safe; only one thread, the +main thread, is allowed to call GTK+ code at all times. + + +Threads: FAQ +------------ + +* I'm porting code from pygtk (GTK+ 2) to PyGObject (GTK+ 3). Has anything + changed regarding threads? + + Short answer: No. + + Long answer: ``gtk.gdk.threads_init()``, ``gtk.gdk.threads_enter()`` and + ``gtk.gdk.threads_leave()`` are now :func:`Gdk.threads_init`, + :func:`Gdk.threads_enter` and :func:`Gdk.threads_leave`. + ``gobject.threads_init()`` can be removed. + +* I'm using :func:`Gdk.threads_init` and want to get rid of it. What do I + need to do? + + * Remove any :func:`Gdk.threads_init()`, :func:`Gdk.threads_enter` and + :func:`Gdk.threads_leave` calls. In case they get executed in a thread, + move the GTK+ code into its own function and schedule it using + :func:`GLib.idle_add`. Be aware that the newly created function will be + executed some time later, so other stuff can happen in between. + + * Replace any call to ``Gdk.threads_add_*()`` with their GLib counterpart. + For example :func:`GLib.idle_add` instead of :func:`Gdk.threads_add_idle`. + +* What about signals and threads? + + Signals get executed in the context they are emitted from. In which context + the object is created or where ``connect()`` is called from doesn't matter. + In GStreamer, for example, some signals can be called from a different + thread, see the respective signal documentation for when this is the case. + In case you connect to such a signal you have to make sure to not call any + GTK+ code or use :func:`GLib.idle_add` accordingly. + +* What if I need to call GTK+ code in signal handlers emitted from a thread? + + In case you have a signal that is emitted from another thread and you need + to call GTK+ code during and not after signal handling, you can push the + operation with an :class:`threading.Event` object to the main loop and wait + in the signal handler until the operation gets scheduled and the result is + available. Be aware that if the signal is emitted from the main loop this + will deadlock. See the following example + + .. code:: python + + # [...] + + toggle_button = Gtk.ToggleButton() + + def signal_handler_in_thread(): + + def function_calling_gtk(event, result): + result.append(toggle_button.get_active()) + event.set() + + event = threading.Event() + result = [] + GLib.idle_add(function_calling_gtk, event, result) + event.wait() + toggle_button_is_active = result[0] + print(toggle_button_is_active) + + # [...] + +* What about the Python `GIL + <https://en.wikipedia.org/wiki/Global_Interpreter_Lock>`__ ? + + Similar to I/O operations in Python, all PyGObject calls release the + GIL during their execution and other Python threads can be executed + during that time. + + +Asynchronous Operations +----------------------- + +In addition to functions for blocking I/O glib also provides corresponding +asynchronous versions, usually with the same name plus a ``_async`` suffix. +These functions do the same operation as the synchronous ones but don't block +during their execution. Instead of blocking they execute the operation in the +background and call a callback once the operation is finished or got canceled. + +The following example shows how to download a web page and display the +source in a text field. In addition it's possible to abort the running +operation. + + +.. code:: python + + import time + + from gi.repository import Gio, GLib, Gtk + + + class DownloadWindow(Gtk.Window): + + def __init__(self): + super(DownloadWindow, self).__init__( + default_width=500, default_height=400, title="Async I/O Example") + + self.cancellable = Gio.Cancellable() + + self.cancel_button = Gtk.Button(label="Cancel") + self.cancel_button.connect("clicked", self.on_cancel_clicked) + self.cancel_button.set_sensitive(False) + + self.start_button = Gtk.Button(label="Load") + self.start_button.connect("clicked", self.on_start_clicked) + + textview = Gtk.TextView() + self.textbuffer = textview.get_buffer() + scrolled = Gtk.ScrolledWindow() + scrolled.add(textview) + + box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, + border_width=12) + box.pack_start(self.start_button, False, True, 0) + box.pack_start(self.cancel_button, False, True, 0) + box.pack_start(scrolled, True, True, 0) + + self.add(box) + + def append_text(self, text): + iter_ = self.textbuffer.get_end_iter() + self.textbuffer.insert(iter_, "[%s] %s\n" % (str(time.time()), text)) + + def on_start_clicked(self, button): + button.set_sensitive(False) + self.cancel_button.set_sensitive(True) + self.append_text("Start clicked...") + + file_ = Gio.File.new_for_uri( + "http://python-gtk-3-tutorial.readthedocs.org/") + file_.load_contents_async( + self.cancellable, self.on_ready_callback, None) + + def on_cancel_clicked(self, button): + self.append_text("Cancel clicked...") + self.cancellable.cancel() + + def on_ready_callback(self, source_object, result, user_data): + try: + succes, content, etag = source_object.load_contents_finish(result) + except GLib.GError as e: + self.append_text("Error: " + e.message) + else: + content_text = content[:100].decode("utf-8") + self.append_text("Got content: " + content_text + "...") + finally: + self.cancellable.reset() + self.cancel_button.set_sensitive(False) + self.start_button.set_sensitive(True) + + + if __name__ == "__main__": + win = DownloadWindow() + win.show_all() + win.connect("destroy", Gtk.main_quit) + + Gtk.main() + + +The example uses the asynchronous version of :meth:`Gio.File.load_contents` to +load the content of an URI pointing to a web page, but first we look at the +simpler blocking alternative: + +We create a :class:`Gio.File` instance for our URI and call +:meth:`Gio.File.load_contents`, which, if it doesn't raise an error, returns +the content of the web page we wanted. + +.. code:: python + + file = Gio.File.new_for_uri("http://python-gtk-3-tutorial.readthedocs.org/") + try: + status, contents, etag_out = file.load_contents(None) + except GLib.GError: + print("Error!") + else: + print(contents) + +In the asynchronous variant we need two more things: + +* A :class:`Gio.Cancellable`, which we can use during the operation to + abort or cancel it. +* And a :func:`Gio.AsyncReadyCallback` callback function, which gets called + once the operation is finished and we can collect the result. + +The window contains two buttons for which we register ``clicked`` signal +handlers: + +* The ``on_start_clicked()`` signal handler calls + :meth:`Gio.File.load_contents_async` with a :class:`Gio.Cancellable` + and ``on_ready_callback()`` as :func:`Gio.AsyncReadyCallback`. +* The ``on_cancel_clicked()`` signal handler calls + :meth:`Gio.Cancellable.cancel` to cancel the running operation. + +Once the operation is finished, either because the result is available, an +error occurred or the operation was canceled, ``on_ready_callback()`` will be +called with the :class:`Gio.File` instance and a :class:`Gio.AsyncResult` +instance which holds the result. + +To get the result we now have to call :meth:`Gio.File.load_contents_finish` +which returns the same things as :meth:`Gio.File.load_contents` except in +this case the result is already there and it will return immediately +without blocking. + +After all this is done we call :meth:`Gio.Cancellable.reset` so the +:class:`Gio.Cancellable` can be re-used for new operations and we can click +the "Load" button again. This works since we made sure that only one +operation can be active at any time by deactivating the "Load" button using +:meth:`Gtk.Widget.set_sensitive`. diff --git a/docs/icons.rst b/docs/icons.rst new file mode 100644 index 00000000..7637df20 --- /dev/null +++ b/docs/icons.rst @@ -0,0 +1,48 @@ +.. |python-logo| raw:: html + + <i class="icon-python"></i> + + +.. |ubuntu-logo| raw:: html + + <i class="icon-ubuntu"></i> + +.. |debian-logo| raw:: html + + <i class="icon-debian"></i> + +.. |fedora-logo| raw:: html + + <i class="icon-fedora"></i> + +.. |opensuse-logo| raw:: html + + <i class="icon-suse"></i> + +.. |windows-logo| raw:: html + + <i class="fa fa-windows"></i> + +.. |source-logo| raw:: html + + <i class="fa fa-file"></i> + +.. |arch-logo| raw:: html + + <i class="icon-archlinux"></i> + +.. |macosx-logo| raw:: html + + <i class="fa fa-apple"></i> + +.. |github-logo| raw:: html + + <i class="fa fa-github"></i> + +.. |bug-logo| raw:: html + + <i class="fa fa-bug"></i> + +.. |linux-logo| raw:: html + + <i class="fa fa-linux"></i> diff --git a/docs/images/LICENSE b/docs/images/LICENSE new file mode 100644 index 00000000..0fbbdbf7 --- /dev/null +++ b/docs/images/LICENSE @@ -0,0 +1,3 @@ +pygobject.svg and pygobject-small.svg are based on the GTK+ logo, created by +Andreas Nilsson, licensed under CC BY-SA 3.0. For more info see +https://commons.wikimedia.org/wiki/File:GTK%2B_logo.svg diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico Binary files differnew file mode 100644 index 00000000..905b2007 --- /dev/null +++ b/docs/images/favicon.ico diff --git a/docs/images/logo.svg b/docs/images/logo.svg new file mode 100644 index 00000000..3f4ebde8 --- /dev/null +++ b/docs/images/logo.svg @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="135" + height="135" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.91 r13725" + version="1.0" + sodipodi:docname="logo.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2897" /> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2450" /> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2474"> + <path + d="m 0,450.7086 121.89,0 0,153.071 -121.89,0 0,-153.071 z" + id="path2476" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2484"> + <path + d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" + id="path2486" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2494"> + <path + d="m 0,1802.8342 487.5601,0 0,578.1658 L 0,2381 0,1802.8342 z" + id="path2496" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2504"> + <path + d="m -1.5e-6,-2.94433 2.3255315,0 0,3.88873 -2.3255315,0 0,-3.88873 z" + id="path2506" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2514"> + <path + d="m 0,1802.8342 487.5601,0 0,578.1658 L 0,2381 0,1802.8342 z" + id="path2516" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2532"> + <path + d="m 9.806,537.3086 104.874,0 0,28.203 -104.874,0 0,-28.203 z" + id="path2534" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2542"> + <path + d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" + id="path2544" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2552"> + <path + d="m 39.2241,2149.2344 419.4961,0 0,112.812 -419.4961,0 0,-112.812 z" + id="path2554" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2562"> + <path + d="m -0.0935124,-19.05134 2.7028824,0 0,21.10663 -2.7028824,0 0,-21.10663 z" + id="path2564" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2572"> + <path + d="m 39.2241,2149.2344 419.4961,0 0,112.812 -419.4961,0 0,-112.812 z" + id="path2574" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2612"> + <path + d="m 0,-9.1245 291.968,0 0,462.668 -291.968,0 0,-462.668 z" + id="path2614" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2618"> + <path + d="m 0,0 283.5,0 0,453.5436 -283.5,0 L 0,0 z" + id="path2620" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2628"> + <path + d="m 1701.323,36.99957 283.465,0 0,595.276 -283.465,0 0,-595.276 z" + id="path2630" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2638"> + <path + d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" + id="path2640" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2644"> + <path + d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" + id="path2646" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2654"> + <path + d="m 8.716e-4,0.0203769 0.9688584,0 0,1.2848631 -0.9688584,0 0,-1.2848631 z" + id="path2656" + inkscape:connector-curvature="0" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2664"> + <path + d="m 0,0 1134,0 0,1814.1743 -1134,0 L 0,0 z" + id="path2666" + inkscape:connector-curvature="0" /> + </clipPath> + <inkscape:perspective + id="perspective2777" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 526.18109 : 1" + sodipodi:type="inkscape:persp3d" /> + <filter + inkscape:collect="always" + style="color-interpolation-filters:sRGB" + id="filter4210" + x="-0.013603581" + width="1.0272072" + y="-0.010734612" + height="1.0214692"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.17314453" + id="feGaussianBlur4212" /> + </filter> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.979899" + inkscape:cx="18.317077" + inkscape:cy="97.877634" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1280" + inkscape:window-height="674" + inkscape:window-x="0" + inkscape:window-y="26" + inkscape:window-maximized="0" + showborder="true" + fit-margin-top="9" + fit-margin-left="9" + fit-margin-right="9" + fit-margin-bottom="9" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-74.24472,-374.35257)"> + <rect + style="fill:#000000;fill-opacity:1" + id="rect3079" + width="117" + height="117" + x="83.24472" + y="383.35257" + ry="23.031063" /> + <g + id="g3855" + transform="translate(0.7466894,0.04879762)" + style="fill:#4e9a06" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4210)" + x="106.41864" + y="461.19006" + id="text4178" + sodipodi:linespacing="125%" + transform="matrix(1.1069586,0,0,1.1069586,-15.44004,-48.180085)"><tspan + sodipodi:role="line" + id="tspan4180" + x="106.41864" + y="461.19006" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:87.5px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';text-align:start;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1">gi</tspan></text> + </g> +</svg> diff --git a/docs/images/overview.dia b/docs/images/overview.dia Binary files differnew file mode 100644 index 00000000..08b02430 --- /dev/null +++ b/docs/images/overview.dia diff --git a/docs/images/overview.svg b/docs/images/overview.svg new file mode 100644 index 00000000..37d6e2c4 --- /dev/null +++ b/docs/images/overview.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"> +<svg width="27cm" height="10cm" viewBox="220 135 524 199" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs/> + <g id="Background"> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #646464" x="456.332" y="136.698" width="134.923" height="196.302" rx="8" ry="8"/> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #5a9fd4" x="221.09" y="214.954" width="80" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="261.09" y="237.604"> + <tspan x="261.09" y="237.604">Python</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #5a9fd4" x="338" y="216.562" width="81.6" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="378.8" y="239.212"> + <tspan x="378.8" y="239.212">PyGObject</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #5a9fd4" x="473.126" y="147.249" width="100.6" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="523.426" y="169.899"> + <tspan x="523.426" y="169.899">libgirepository</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #5a9fd4" x="483.752" y="192.25" width="80" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="523.752" y="214.9"> + <tspan x="523.752" y="214.9">libglib</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #5a9fd4" x="483.834" y="238.25" width="80" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="523.834" y="260.9"> + <tspan x="523.834" y="260.9">libgobject</tspan> + </text> + </g> + <g> + <line style="fill: none; stroke-opacity: 1; stroke-width: 2; stroke-linejoin: round; stroke: #646464" x1="301.09" y1="232.954" x2="330.289" y2="233.558"/> + <polygon style="fill: #646464; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #646464" fill-rule="evenodd" points="334.788,233.651 328.727,236.527 330.289,233.558 328.851,230.528 "/> + </g> + <g> + <line style="fill: none; stroke-opacity: 1; stroke-width: 2; stroke: #646464" x1="419.6" y1="234.562" x2="449.596" y2="234.796"/> + <polygon style="fill: #646464; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #646464" fill-rule="evenodd" points="454.096,234.831 448.073,237.784 449.596,234.796 448.12,231.784 "/> + </g> + <g> + <path style="fill: none; stroke-opacity: 1; stroke-width: 2; stroke: #646464" d="M 591.256 234.848 C 615.096,234.848 615.096,200.938 632.302,200.938"/> + <polygon style="fill: #646464; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #646464" fill-rule="evenodd" points="636.802,200.938 630.802,203.938 632.302,200.938 630.802,197.938 "/> + </g> + <g> + <path style="fill: none; stroke-opacity: 1; stroke-width: 2; stroke: #646464" d="M 591.256 234.848 C 615.096,234.848 615.096,270.234 631.594,270.234"/> + <polygon style="fill: #646464; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #646464" fill-rule="evenodd" points="636.094,270.234 630.094,273.234 631.594,270.234 630.094,267.234 "/> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #5a9fd4" x="484" y="285.9" width="80" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="524" y="308.55"> + <tspan x="524" y="308.55">libffi</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #5a9fd4" x="639.038" y="182.938" width="104.05" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="691.063" y="205.588"> + <tspan x="691.063" y="205.588">Gtk-3.0.typelib</tspan> + </text> + </g> + <g> + <rect style="fill: #ffffff; fill-opacity: 1; stroke-opacity: 1; stroke-width: 2; stroke: #5a9fd4" x="638.33" y="252.234" width="80" height="36" rx="10" ry="10"/> + <text font-size="12.8" style="fill: #646464; fill-opacity: 1; stroke: none;text-anchor:middle;font-family:Lato;font-style:normal;font-weight:500" x="678.33" y="274.884"> + <tspan x="678.33" y="274.884">libgtk-3.so</tspan> + </text> + </g> + </g> +</svg> diff --git a/docs/images/pygobject-small.svg b/docs/images/pygobject-small.svg new file mode 100644 index 00000000..e6576e81 --- /dev/null +++ b/docs/images/pygobject-small.svg @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="88.572403" + height="96.050858" + id="svg6843" + sodipodi:docname="pygobject-small.svg" + inkscape:version="0.92.1 r15371"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="674" + id="namedview10" + showgrid="false" + inkscape:zoom="1.2285173" + inkscape:cx="135.96584" + inkscape:cy="-1.8615718" + inkscape:window-x="0" + inkscape:window-y="26" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs6845"> + <linearGradient + inkscape:collect="always" + id="linearGradient4534"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop4530" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop4532" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4522"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop4518" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop4520" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4660"> + <stop + style="stop-color:#646464;stop-opacity:1;" + offset="0" + id="stop4656" /> + <stop + style="stop-color:#ffffff;stop-opacity:1" + offset="1" + id="stop4658" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4652"> + <stop + style="stop-color:#5a9fd4;stop-opacity:1;" + offset="0" + id="stop4648" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.94650203" + offset="1" + id="stop4650" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4644"> + <stop + style="stop-color:#edd400;stop-opacity:1;" + offset="0" + id="stop4640" /> + <stop + style="stop-color:#ffffff;stop-opacity:1" + offset="1" + id="stop4642" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4644" + id="linearGradient4646" + x1="53.816978" + y1="111.10486" + x2="20.88413" + y2="30.82696" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4652" + id="linearGradient4654" + x1="70.43454" + y1="17.875593" + x2="53.816978" + y2="111.10486" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4660" + id="linearGradient4662" + x1="23.216625" + y1="81.319481" + x2="107.33282" + y2="39.060543" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4522" + id="linearGradient4524" + x1="70.587303" + y1="17.177763" + x2="70.485733" + y2="67.361443" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4534" + id="linearGradient4536" + x1="69.029457" + y1="87.363297" + x2="70.373047" + y2="68.046875" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + transform="translate(-19.822261,-15.90723)" + id="layer1"> + <g + id="g4527" + transform="translate(0,-0.20854102)"> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:1;fill:url(#linearGradient4654);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12400007;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6976" + d="M 20.88413,30.82696 53.816977,55.527708 107.33282,39.060543 70.587303,17.177763 Z" /> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient4662);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6978" + d="M 22.94243,82.287118 20.88413,30.82696 53.816977,55.527708 v 55.577152 z" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:1;fill:url(#linearGradient4646);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6980" + d="M 53.816977,111.10486 103.21619,90.5207 107.33282,39.060543 53.816977,55.527708 Z" /> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4536);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 70.597656,66.675781 -47.558594,14.044922 0.355469,1.197266 46.978516,-13.871094 32.652343,22.910156 0.71875,-1.023437 z" + id="path6982" + inkscape:connector-curvature="0" /> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4524);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 69.808594,17.875 v 49.109375 h 1.25 V 17.875 Z" + id="path6984" + inkscape:connector-curvature="0" /> + </g> + </g> +</svg> diff --git a/docs/images/pygobject.svg b/docs/images/pygobject.svg new file mode 100644 index 00000000..fbf88e15 --- /dev/null +++ b/docs/images/pygobject.svg @@ -0,0 +1,244 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="392.86777" + height="96.050858" + id="svg6843" + sodipodi:docname="pygobject.svg" + inkscape:version="0.92.1 r15371"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1366" + inkscape:window-height="674" + id="namedview10" + showgrid="false" + inkscape:zoom="1.2285173" + inkscape:cx="135.96584" + inkscape:cy="-1.8615724" + inkscape:window-x="0" + inkscape:window-y="26" + inkscape:window-maximized="1" + inkscape:current-layer="g4527" /> + <defs + id="defs6845"> + <linearGradient + inkscape:collect="always" + id="linearGradient4534"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop4530" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop4532" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4522"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop4518" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop4520" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4660"> + <stop + style="stop-color:#646464;stop-opacity:1;" + offset="0" + id="stop4656" /> + <stop + style="stop-color:#ffffff;stop-opacity:1" + offset="1" + id="stop4658" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4652"> + <stop + style="stop-color:#5a9fd4;stop-opacity:1;" + offset="0" + id="stop4648" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.94650203" + offset="1" + id="stop4650" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient4644"> + <stop + style="stop-color:#edd400;stop-opacity:1;" + offset="0" + id="stop4640" /> + <stop + style="stop-color:#ffffff;stop-opacity:1" + offset="1" + id="stop4642" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4644" + id="linearGradient4646" + x1="53.816978" + y1="111.10486" + x2="20.88413" + y2="30.82696" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4652" + id="linearGradient4654" + x1="70.43454" + y1="17.875593" + x2="53.816978" + y2="111.10486" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4660" + id="linearGradient4662" + x1="23.216625" + y1="81.319481" + x2="107.33282" + y2="39.060543" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4522" + id="linearGradient4524" + x1="70.587303" + y1="17.177763" + x2="70.485733" + y2="67.361443" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4534" + id="linearGradient4536" + x1="69.029457" + y1="87.363297" + x2="70.373047" + y2="68.046875" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + transform="translate(-19.822261,-15.90723)" + id="layer1"> + <g + id="g4527" + transform="translate(0,-0.20854102)"> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:1;fill:url(#linearGradient4654);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12400007;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6976" + d="M 20.88413,30.82696 53.816977,55.527708 107.33282,39.060543 70.587303,17.177763 Z" /> + <path + inkscape:connector-curvature="0" + style="display:inline;fill:url(#linearGradient4662);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6978" + d="M 22.94243,82.287118 20.88413,30.82696 53.816977,55.527708 v 55.577152 z" /> + <path + inkscape:connector-curvature="0" + style="display:inline;opacity:1;fill:url(#linearGradient4646);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path6980" + d="M 53.816977,111.10486 103.21619,90.5207 107.33282,39.060543 53.816977,55.527708 Z" /> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4536);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 70.597656,66.675781 -47.558594,14.044922 0.355469,1.197266 46.978516,-13.871094 32.652343,22.910156 0.71875,-1.023437 z" + id="path6982" + inkscape:connector-curvature="0" /> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4524);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" + d="m 69.808594,17.875 v 49.109375 h 1.25 V 17.875 Z" + id="path6984" + inkscape:connector-curvature="0" /> + </g> + <g + aria-label="PyGObject" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:25px;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:-2px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text4518" + transform="matrix(0.73060434,0,0,0.73060434,39.415227,17.281548)"> + <path + d="m 134.29489,66.572751 c 14.8,0 26.88,-2.96 26.88,-17.44 0,-10.96 -7.68,-16.4 -22.96,-16.4 h -18.32 v 55.36 h 9.84 v -21.52 z m 16.8,-17.04 c 0,7.44 -7.76,8 -16.4,8 h -4.96 v -15.76 h 7.44 c 7.36,0 13.92,0.96 13.92,7.76 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4529" + inkscape:connector-curvature="0" /> + <path + d="m 164.91864,49.612751 17.44,38.8 -8.8,20.399999 h 10.8 l 23.6,-59.199999 h -10.16 l -10.4,29.52 -11.44,-29.52 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4531" + inkscape:connector-curvature="0" /> + <path + d="m 211.70114,60.092751 c 0,18.64 11.12,28.8 27.68,28.8 9.68,0 17.04,-2.4 22.4,-6.64 v -25.44 h -24.4 v 9.04 h 14.56 v 11.68 c -3.28,1.6 -5.84,2.32 -10.96,2.32 -11.28,0 -19.44,-6.48 -19.44,-20.16 0,-12.96 6.08,-19.04 19.68,-19.04 6.4,0 12,2.24 16.24,4.4 l 2.72,-8.72 c -5.28,-3.2 -12.48,-4.72 -19.2,-4.72 -19.52,0 -29.28,11.36 -29.28,28.48 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4533" + inkscape:connector-curvature="0" /> + <path + d="m 297.97114,31.612751 c -16.48,0 -27.52,11.92 -27.52,28.64 0,16.8 10.88,28.64 27.2,28.64 16.8,0 27.84,-12.24 27.84,-29.2 0,-16.64 -11.04,-28.08 -27.52,-28.08 z m -0.4,9.04 c 11.12,0 18.08,8.08 18.08,19.6 0,11.52 -6.24,19.6 -17.36,19.6 -11.2,0 -18,-8.72 -18,-20.24 0,-11.28 6.32,-18.96 17.28,-18.96 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4535" + inkscape:connector-curvature="0" /> + <path + d="m 340.09739,88.092751 1.92,-2.48 c 3.84,2.24 7.68,3.28 11.6,3.28 11.52,0 18.32,-8.56 18.32,-20.24 0,-11.68 -4.72,-19.92 -16.56,-19.92 -4.56,0 -8.32,1.12 -11.6,2.8 v -20.88 h -9.84 v 57.44 z m 3.68,-29.2 c 1.92,-0.8 5.68,-2.16 9.2,-2.16 6.88,0 9.12,4.96 9.12,12.48 0,7.52 -3.52,11.92 -10.08,11.92 -3.2,0 -5.92,-0.8 -8.24,-2.64 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4537" + inkscape:connector-curvature="0" /> + <path + d="m 385.06739,44.972751 c 3.12,0 5.92,-2.8 5.92,-5.92 0,-3.12 -2.8,-5.92 -5.92,-5.92 -3.12,0 -5.92,2.8 -5.92,5.92 0,3.12 2.8,5.92 5.92,5.92 z m -8.48,56.319999 c -1.2,0 -2.24,-0.24 -2.24,-0.24 l -1.92,7.36 c 0,0 2.64,0.8 5.44,0.8 10.16,0 12.24,-6.96 12.24,-13.999999 v -45.6 h -9.84 v 43.6 c 0,4.96 -0.56,8.079999 -3.68,8.079999 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4539" + inkscape:connector-curvature="0" /> + <path + d="m 420.17989,81.132751 c -9.44,0 -11.6,-4.08 -12,-9.04 h 26.4 v -3.76 c 0,-12.56 -5.92,-19.6 -17.44,-19.6 -11.44,0 -18.88,8.96 -18.88,20.08 0,12.48 7.68,20.08 20.64,20.08 5.12,0 10.08,-0.88 14.8,-2.4 l -1.92,-7.36 c -3.52,1.36 -7.36,2 -11.6,2 z m -11.92,-15.84 c 0.48,-4.64 2.48,-8.96 9.04,-8.96 4.8,0 7.44,2.8 7.44,8.96 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4541" + inkscape:connector-curvature="0" /> + <path + d="m 450.44364,68.812751 c 0,-7.44 4.4,-12.4 12.8,-12.4 5.04,0 7.84,1.2 9.6,2.16 l 1.92,-7.36 c -1.92,-1.2 -5.44,-2.48 -12.56,-2.48 -13.2,0 -21.6,7.76 -21.6,20.08 0,12 8.72,20.08 21.92,20.08 6.08,0 11.04,-1.76 12.4,-2.4 l -1.92,-7.36 c -1.68,0.8 -4.72,2.08 -9.76,2.08 -7.92,0 -12.8,-5.12 -12.8,-12.4 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4543" + inkscape:connector-curvature="0" /> + <path + d="m 510.91239,86.732751 -1.44,-6.8 c -1.44,0.4 -4.4,1.12 -7.12,1.12 -5.28,0 -6.48,-2.64 -6.48,-5.6 v -18.16 h 13.28 v -7.68 h -13.28 v -12.08 h -9.84 v 12.08 h -6.4 v 7.68 h 6.4 v 18.4 c 0,6.8 1.68,13.2 13.92,13.2 3.68,0 8.24,-1.12 10.96,-2.16 z" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:80px;font-family:Cantarell;-inkscape-font-specification:'Cantarell Bold';letter-spacing:0px;word-spacing:0px;fill:#646464;fill-opacity:1" + id="path4545" + inkscape:connector-curvature="0" /> + </g> + </g> +</svg> diff --git a/docs/images/start_linux.png b/docs/images/start_linux.png Binary files differnew file mode 100644 index 00000000..5a557ee4 --- /dev/null +++ b/docs/images/start_linux.png diff --git a/docs/images/start_macos.png b/docs/images/start_macos.png Binary files differnew file mode 100644 index 00000000..8b35a95c --- /dev/null +++ b/docs/images/start_macos.png diff --git a/docs/images/start_windows.png b/docs/images/start_windows.png Binary files differnew file mode 100644 index 00000000..db4ce325 --- /dev/null +++ b/docs/images/start_windows.png diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..82e76a95 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,89 @@ +.. include:: icons.rst + +.. title:: Overview + +.. toctree:: + :hidden: + :titlesonly: + :maxdepth: 1 + + getting_started + changelog + guide/index + devguide/index + packagingguide + maintguide + further + contact + +.. image:: images/pygobject.svg + :align: center + :width: 400px + :height: 98px + +| + +.. include:: ../README.rst + :start-after: | + :end-before: ---- + +If you want to write a Python application for `GNOME +<https://www.gnome.org/>`__ or a Python GUI application using GTK+, then +PyGObject is the way to go. For more information on specific libraries check +out the "`Python GTK+ 3 Tutorial +<https://python-gtk-3-tutorial.readthedocs.io>`__" and the "`Python GI API +Reference <https://lazka.github.io/pgi-docs>`__". + +.. code:: python + + import gi + gi.require_version("Gtk", "3.0") + from gi.repository import Gtk + + window = Gtk.Window(title="Hello World") + window.show() + window.connect("destroy", Gtk.main_quit) + Gtk.main() + + +How does it work? +----------------- + +.. figure:: images/overview.svg + :width: 600px + :height: 222px + :align: center + +PyGObject uses `glib <https://developer.gnome.org/glib/stable/>`__, `gobject +<https://developer.gnome.org/gobject/stable/>`__, `girepository +<https://developer.gnome.org/gi/stable/>`__, `libffi +<https://sourceware.org/libffi/>`__ and other libraries to access the C +library (libgtk-3.so) in combination with the additional metadata from the +accompanying typelib file (Gtk-3.0.typelib) and dynamically provides a Python +interface based on that information. + + +Who Is Using PyGObject? +----------------------- + +* `D-Feet <https://wiki.gnome.org/action/show/Apps/DFeet>`__ - an easy to use D-Bus debugger +* `GNOME Music <https://wiki.gnome.org/Apps/Music>`__ - a music player for GNOME +* `GNOME Tweak Tool <https://wiki.gnome.org/action/show/Apps/GnomeTweakTool>`__ - a tool to customize advanced GNOME 3 options +* `Gramps <https://gramps-project.org/>`__ - a genealogy program +* `Lollypop <https://gnumdk.github.io/lollypop-web/>`__ - a modern music player +* `Meld <http://meldmerge.org/>`__ - a visual diff and merge tool +* `MyPaint <http://mypaint.org/>`__ - a nimble, distraction-free, and easy tool for digital painters +* `Orca <https://wiki.gnome.org/Projects/Orca>`__ - a flexible and extensible screen reader +* `Pithos <https://pithos.github.io/>`__ - a Pandora Radio client +* `Pitivi <http://www.pitivi.org/>`__ - a free and open source video editor +* `Quod Libet <https://quodlibet.readthedocs.io/>`__ - a music library manager / player +* `Transmageddon <http://www.linuxrising.org/>`__ - a video transcoder + + +The following applications or libraries use PyGObject for optional features, +such as plugins or as optional backends: + +* `beets <http://beets.io/>`__ - a music library manager and MusicBrainz tagger +* `gedit <https://wiki.gnome.org/Apps/Gedit>`_- a GNOME text editor +* `matplotlib <http://matplotlib.org/>`__ - a python 2D plotting library +* `Totem <https://wiki.gnome.org/Apps/Videos>`__ - a video player for GNOME diff --git a/docs/maintguide.rst b/docs/maintguide.rst new file mode 100644 index 00000000..c9cec1b9 --- /dev/null +++ b/docs/maintguide.rst @@ -0,0 +1,32 @@ +================ +Maintainer Guide +================ + +Making a Release +---------------- + +#. Make sure configure.ac has the right version number +#. Update NEWS file (use ``make release-news`` target and then edit as you see + fit) +#. Run ``make distcheck``, fix any issues and commit. +#. Commit NEWS as ``"release 3.X.Y"`` and push +#. Tag with: ``git tag -s 3.X.Y -m "release 3.X.Y"`` +#. Push tag with: ``git push origin 3.X.Y`` +#. Commit post-release version bump to configure.ac +#. Upload tarball: ``scp pygobject-3.X.Y.tar.gz user@master.gnome.org:`` +#. Install tarball: + ``ssh user@master.gnome.org 'ftpadmin install pygobject-3.X.Y.tar.gz'`` + +Based on https://wiki.gnome.org/MaintainersCorner/Releasing + + +Branching +--------- + +Each cycle after the feature freeze, we create a stable branch so development +can continue in the master branch unaffected by the freezes. + +#. Create the branch locally with: ``git checkout -b pygobject-3-2`` +#. Push new branch: ``git push origin pygobject-3-2`` +#. In master, update configure.ac to what will be the next version number + (3.3.0) diff --git a/docs/packagingguide.rst b/docs/packagingguide.rst new file mode 100644 index 00000000..ab1fffe7 --- /dev/null +++ b/docs/packagingguide.rst @@ -0,0 +1,55 @@ +Packaging Guide +=============== + +Some notes on how to package PyGObject + +Source packages can be found at +https://ftp.gnome.org/pub/GNOME/sources/pygobject + + +Existing Packages: + +* https://www.archlinux.org/packages/extra/x86_64/python-gobject +* https://packages.qa.debian.org/p/pygobject.html +* https://github.com/Alexpux/MINGW-packages/tree/master/mingw-w64-pygobject + + +Building:: + + ./configure --with-python=${PYTHON} --prefix="${PREFIX}" + make check # if you want to run the test suite + make DESTDIR="${PKGDIR}" install + +Runtime dependencies: + + * glib + * libgirepository (gobject-introspection) + * libffi + * Python 2 or 3 + + The overrides directory contains various files which includes various + Python imports mentioning gtk, gdk etc. They are only used when the + corresponding library is present, they are not direct dependencies. + +Build dependencies: + + * The runtime dependencies + * cairo (optional) + * pycairo (optional) + * pkg-config + + If autotools is used: + + * gnome-common for PyGObject < 3.26 + * autoconf-archive for PyGObject >= 3.26 + + If setup.py is used: + + * setuptools + +Test Suite dependencies: + + * The runtime dependencies + * GTK+ 3 (optional) + * pango (optional) + * pycairo (optional) @@ -323,6 +323,10 @@ def main(): for s in cairo_sources: sources.remove(s) + readme = os.path.join(script_dir, "README.rst") + with io.open(readme, encoding="utf-8") as h: + long_description = h.read() + gi_ext = Extension( name='gi._gi', sources=sources, @@ -347,7 +351,7 @@ def main(): maintainer=pkginfo["Maintainer"], maintainer_email=pkginfo["Maintainer-email"], license=pkginfo["License"], - long_description=pkginfo["Description"], + long_description=long_description, platforms=pkginfo.get_all("Platform"), classifiers=pkginfo.get_all("Classifier"), packages=find_packages(script_dir), |