Added documentation

This commit is contained in:
Runar Tenfjord 2012-10-24 14:09:39 +02:00
parent 1c25435152
commit f78c4e20ae
14 changed files with 552 additions and 8 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
* text=auto

15
.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
# build folders
gltools/build/
gltool/@docs/build/
gltool/@docs/html/
# compiled python files
*.pyc
*.pyo
# python extension modules
*.pyd
*.so
# libraries
*.dll
*.a
# object files
*.o

View file

@ -2,7 +2,7 @@ Introduction
============
gltools is library for quickly creating OpenGL based
application with support for:
application in Python/Cython with support for:
* Access to vertex buffers and GLSL shaders
* Access to truetype fonts
@ -28,7 +28,9 @@ The extension have only been build on the Linux platform.
Documentation
=============
ToDo
See online Sphinx docs_
.. _docs: http://tenko.github.com/gltools/index.html
.. _geotools: http://github.com/tenko/geotools

11
gltools/@docs/conf.py Normal file
View file

@ -0,0 +1,11 @@
source_suffix = '.rst'
master_doc = 'index'
project = 'gltools'
copyright = '2012, Runar Tenfjord'
extensions = ['sphinx.ext.autodoc']
autodoc_docstring_signature = True
autodoc_member_order = 'groupwise'
html_style = 'default.css'
htmlhelp_basename = 'gltoolsdoc'

89
gltools/@docs/content.rst Normal file
View file

@ -0,0 +1,89 @@
GLTools
=======
ColorRGBA
---------
.. autoclass:: gltools.ColorRGBA
:members:
:special-members:
Material
--------
.. autoclass:: gltools.Material
:members:
:special-members:
Light
-----
.. autoclass:: gltools.Light
:members:
:special-members:
ClientBuffer
------------
.. autoclass:: gltools.ClientBuffer
:members:
:special-members:
ShaderProgram
-------------
.. autoclass:: gltools.ShaderProgram
:members:
:special-members:
.. autofunction:: gltools.Init
.. autofunction:: gltools.getTime
.. autofunction:: gltools.SetTime
.. autofunction:: gltools.SetGamma
.. autofunction:: gltools.GetDesktopSize
Window
------
.. autoclass:: gltools.Window
:members:
:special-members:
UI
--
.. autoclass:: gltools.UI
:members:
:special-members:
openGL
------
.. autofunction:: gltools.InitGLExt
.. autofunction:: gltools.BeginText
.. autofunction:: gltools.DrawText
.. autofunction:: gltools.EndText
.. autofunction:: gltools.BlendFunc
.. autofunction:: gltools.Clear
.. autofunction:: gltools.ClearColor
.. autofunction:: gltools.ClearDepth
.. autofunction:: gltools.Color
.. autofunction:: gltools.Disable
.. autofunction:: gltools.DrawArrays
.. autofunction:: gltools.DrawElements
.. autofunction:: gltools.Enable
.. autofunction:: gltools.LineWidth
.. autofunction:: gltools.LightModeli
.. autofunction:: gltools.LoadIdentity

33
gltools/@docs/index.rst Normal file
View file

@ -0,0 +1,33 @@
gltools documentation
=====================
**Overview**
gltools is library for quickly creating OpenGL based
application in Python/Cython with support for:
* Access to vertex buffers and GLSL shaders
* Access to truetype fonts
* Windows handling through GLFW
* Simple GUI controls
OpenGL version 2.1 is targeted which should be available
in most computers these days, even in a laptop's integrated
graphics.
The license is GPL v2.
API Docs
========
.. toctree::
:maxdepth: 2
content
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View file

@ -6,6 +6,10 @@
cdef class ClientBuffer:
'''
Abstraction of OpenGL vertex buffer
The class initialize a single buffer object.
The target argument is either gl.ARRAY_BUFFER
or gl.ELEMENT_ARRAY_BUFFER.
'''
def __init__(self, target = GL_ARRAY_BUFFER):
if not isGLExtLoaded:
@ -27,18 +31,34 @@ cdef class ClientBuffer:
return "()"
cpdef bind(self):
'''
Bind the buffer object and possible set the attribute pointers
ig the target is gl.ARRAY_BUFFER and the datatype is defined
'''
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
buf.bind()
cpdef unBind(self):
'''
Unbind the buffer object
'''
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
buf.unBind()
cpdef setDataType(self, int type, int dataType, int dataTypeSize,
int stride, size_t pointer):
'''
Set datatye for data in buffer. Pointer is an integer with an
offset into the buffer with optional stride.
Set datatye for data in buffer. Only makes sense when
target is gl.ARRAY_BUFFER.
:type: gl.VERTEX_ARRAY, gl.NORMAL_ARRAY or gl.COLOR_ARRAY.
:dataType: gl.FLOAT, gl.INT etc.
:dataTypeSize: size of datatype.
:stride: stride between data
:pointer: pointer into buffer object (offser from index 0)
example::
buffer.setDataType(gl.VERTEX_ARRAY, gl.FLOAT, 3, 0, 0)
'''
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
@ -54,6 +74,10 @@ cdef class ClientBuffer:
'''
Upload data to client side buffer. Passing None
for data will reserve capacity.
:data: None, or any python python object with buffer interface
:size: size of data to upload.
:offset: offset into buffer object
'''
if data is None:
self.cloadData(NULL, size, offset, usage)

View file

@ -3,7 +3,10 @@
# This file is part of gltools - See LICENSE.txt
#
cdef class ColorRGBA:
'''RGBA color'''
'''
RGBA color with components stored as unsigned
bytes.
'''
def __init__(self, GLubyte red = 255, GLubyte green = 255, GLubyte blue = 255,
GLubyte alpha = 255):
self.red = red
@ -34,7 +37,7 @@ cdef class ColorRGBA:
def __mul__(double factor, ColorRGBA rhs):
'''
Leaves alpha unchanged
Scale color components and leaves alpha unchanged
'''
cdef ColorRGBA ret = ColorRGBA.__new__(ColorRGBA)
@ -49,6 +52,9 @@ cdef class ColorRGBA:
return ret
cpdef ColorRGBA copy(self, int red = -1, int green = -1, int blue = -1, alpha = -1):
'''
Create copy with optional changes.
'''
cdef ColorRGBA ret = ColorRGBA.__new__(ColorRGBA)
ret.red = self.red
@ -71,9 +77,15 @@ cdef class ColorRGBA:
return ret
cpdef unsigned toInt(self):
'''
Pack color to a single unsigned int
'''
return self.alpha << 24 | self.blue << 16 | self.green << 8 | self.red
cpdef tuple toFloatVector(self):
'''
Return color as float normalized [0.0 - 1.0]
'''
return (self.red / 255., self.green / 255., self.blue / 255., self.alpha / 255.)
cdef setFloatVector(self, float *vec):
@ -87,7 +99,7 @@ BLACK = ColorRGBA(0,0,0,255)
cdef class Material:
'''
Abstrction of OpenGL material
Abstraction of OpenGL material
'''
def __init__(self, int mode = GL_FRONT_AND_BACK, **kwargs):
self.mode = mode
@ -106,6 +118,9 @@ cdef class Material:
return "()"
cpdef enable(self):
'''
Set OpenGL material state
'''
cdef float mat[4]
cdef int i
if not self.ambient is None:
@ -164,6 +179,9 @@ cdef class Light:
return "()"
cpdef enable(self):
'''
Enable light and set OpenGL state
'''
cdef float mat[4]
glEnable(self.index)
@ -189,4 +207,7 @@ cdef class Light:
glLightfv(self.index, GL_POSITION, mat)
cpdef disable(self):
'''
Disable light
'''
glDisable(self.index)

View file

@ -7,31 +7,81 @@ from glLib cimport *
# init OpenGL function pointers
cpdef InitGLExt():
'''
Initialize OpenGL 2.1 extension
Raise GLError if extensions not found
'''
if not c_initGLExt():
raise GLError(errorMessage)
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor):
'''
Specify pixel arithmetic
:sfactor: Specifies how the red, green, blue, and alpha source blending
factors are computed. The initial value is GL_ONE.
:dfactor: Specifies how the red, green, blue, and alpha destination
blending factors are computed. gl.ONE_MINUS_SRC_COLOR etc.
'''
glBlendFunc(sfactor, dfactor)
cpdef Clear(unsigned int mask):
'''
Clear selected buffers to preset values.
:mask: bit flags are gl.COLOR_BUFFER_BIT, gl.DEPTH_BUFFER_BIT, and
gl.STENCIL_BUFFER_BIT
'''
glClear(mask)
cpdef ClearColor(ColorRGBA col):
'''
Specify clear values for the color buffers
'''
glClearColor(col.red / 255., col.green / 255., col.blue / 255., col.alpha / 255.)
cpdef ClearDepth(double depth):
'''
Specify the clear value for the depth buffer
'''
glClearDepth(depth)
cpdef Color(ColorRGBA col):
'''
Sets the current color.
'''
glColor4ub(col.red, col.green, col.blue, col.alpha )
cpdef Disable(unsigned int cap):
'''
Disable server-side GL capabilities
'''
glDisable(cap)
cpdef DrawArrays(unsigned int mode, int first, int count):
'''
Render primitives from array data
:mode: Primitive type gl.POINTS, gl.LINE_STRIP, etc.
:first: Specifies the starting index in the enabled arrays.
:count: Specifies the number of indices to be rendered.
'''
glDrawArrays(mode, first, count)
cpdef DrawElements(unsigned int mode, int count, int type, indices):
'''
Render primitives from array data with indices.
:mode: Primitive type gl.POINTS, gl.LINE_STRIP, etc.
:count: Specifies the number of indices to be rendered.
:type: Indices data type. One of gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT, or
gl.UNSIGNED_INT
:indices: Either a python object with valid buffer interface or and
integer as a pointer into a already bound ClientBuffer of
element array type.
'''
cdef size_t offset
if isinstance(indices, int):
offset = indices
@ -40,18 +90,36 @@ cpdef DrawElements(unsigned int mode, int count, int type, indices):
glDrawElements(mode, count, type, getVoidPtr(indices))
cpdef Enable(unsigned int cap):
'''
Enable server-side GL capabilities
'''
glEnable(cap)
cpdef LineWidth(float width):
'''
Specify the width of rasterized lines
'''
glLineWidth(width)
cpdef LightModeli(int pname, int param):
'''
Sets lighting model parameters.
Example::
gl.LightModeli(gl.LIGHT_MODEL_TWO_SIDE, gl.TRUE)
'''
glLightModeli(pname, param)
cpdef LoadIdentity():
'''
Replace the current matrix with the identity matrix
'''
glLoadIdentity()
cpdef LoadMatrixd(Transform tr):
'''
Replace the current matrix with given matrix.
'''
cdef double cm[16]
# col 1
@ -81,15 +149,44 @@ cpdef LoadMatrixd(Transform tr):
glLoadMatrixd(cm)
cpdef MatrixMode(unsigned int mode):
'''
Specify which matrix is the current matrix
:mode: gl.MODELVIEW, gl.PROJECTION, or gl.TEXTURE
'''
glMatrixMode(mode)
cpdef Ortho(double left, double right, double bottom, double top, double zNear,
double zFar):
'''
Multiply the current matrix with an orthographic matrix
:left: Specify the coordinates for the left vertical clipping plane.
:right: Specify the coordinates for the vertical clipping plane.
:bottom: Specify the coordinates for the bottom horizontal clipping plane.
:top: Specify the coordinates for the top horizontal clipping plane.
:zNear: Specify the distances to the nearer clipping plane.
:zFar: Specify the distances to the farther depth clipping plane.
'''
glOrtho(left, right, bottom, top, zNear, zFar)
cpdef PolygonMode(unsigned int face, unsigned int mode):
'''
Select a polygon rasterization mode
Example::
gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
'''
glPolygonMode(face, mode)
cpdef Viewport(int x, int y, int width, int height):
'''
Set the viewport
:x: x coordiante of lower left corner.
:y: y coordiante of lower left corner.
:width: viewport width
:height: viewport height
'''
glViewport(x, y, width, height)

View file

@ -3,25 +3,42 @@
from glfwLib cimport *
cpdef Init():
'''
Initialize GLFW.
Raise GLError on failure
'''
if not glfwInit():
raise GLError('failed to initialize glfw')
# timer functions
cpdef double getTime():
'''
Get current time since call to Init as float value
'''
Init()
return glfwGetTime()
cpdef SetTime(double time):
'''
Sets current time
'''
Init()
glfwSetTime(time)
# gamma value
cpdef SetGamma(float gamma):
'''
Set gamma value
'''
Init()
glfwSetGamma(gamma)
# get desktop size
cpdef tuple GetDesktopSize():
'''
Return desktop size
'''
cdef GLFWvidmode vidmode
Init()
@ -30,6 +47,12 @@ cpdef tuple GetDesktopSize():
cdef class Window:
'''
GLFW based window
If width and height are not set then the window is
sized to the current desktop size
'''
def __init__(self, int width = -1, int height = -1, title = None,
bint fullscreen = False):
cdef GLFWvidmode vidmode
@ -96,6 +119,9 @@ cdef class Window:
glfwTerminate()
cpdef setTitle(self, title):
'''
Set window title
'''
cdef char *c_title
# decode to UTF-8
@ -105,54 +131,99 @@ cdef class Window:
glfwSetWindowTitle(<GLFWwindow>self.thisptr, c_title)
cpdef tuple getSize(self):
'''
Get window size
'''
cdef int width, height
glfwGetWindowSize(<GLFWwindow>self.thisptr, &width, &height)
return width, height
cpdef setSize(self, int width, int height):
'''
Set window size
'''
if width <= 0 or height <= 0:
raise GLError('window size not valid')
glfwSetWindowSize(<GLFWwindow>self.thisptr, width, height)
cpdef tuple getPos(self):
'''
Get current window position
'''
cdef int x, y
glfwGetWindowPos(<GLFWwindow>self.thisptr, &x, &y)
return x, y
cpdef setPos(self, int x, int y):
'''
Set current window position
'''
glfwSetWindowPos(<GLFWwindow>self.thisptr, x, y)
cpdef setClipboard(self, content):
'''
Set clipboard text
'''
glfwSetClipboardString(<GLFWwindow>self.thisptr, content)
cpdef getClipboard(self):
'''
Get clipboard text
'''
cdef char *content = glfwGetClipboardString(<GLFWwindow>self.thisptr)
return content
cpdef iconify(self):
'''
Iconify window
'''
glfwIconifyWindow(<GLFWwindow>self.thisptr)
cpdef restore(self):
'''
Restore window from iconification
'''
glfwRestoreWindow(<GLFWwindow>self.thisptr)
cpdef show(self):
'''
Show window
'''
glfwShowWindow(<GLFWwindow>self.thisptr)
cpdef hide(self):
'''
Hide window
'''
glfwHideWindow(<GLFWwindow>self.thisptr)
cpdef close(self):
'''
Stop main loop and close window
'''
self.running = False
glfwDestroyWindow(<GLFWwindow>self.thisptr)
glfwTerminate()
cpdef makeContextCurrent(self):
'''
Make window openGL context current
'''
glfwMakeContextCurrent(<GLFWwindow>self.thisptr)
cpdef swapBuffers(self):
'''
Swap front and back buffers
'''
glfwSwapBuffers(<GLFWwindow>self.thisptr)
cpdef mainLoop(self):
'''
Run main loop.
The main loops waits for events. Mouse move events are special
handled to avoid to quick update.
'''
# keep waiting for events until running is False
cdef int x, y, lastX, lastY
cdef double t
@ -182,36 +253,69 @@ cdef class Window:
break
cpdef onSize(self, int w, int h):
'''
Callback when size changes
'''
pass
cpdef onRefresh(self):
'''
Callback when refresh of content is requested
'''
pass
cpdef onCursorPos(self, int x, int y):
'''
Callback on change of mouse cursor position
'''
pass
cpdef onMouseButton(self, int button, int action):
'''
Callback on mouse button press or release
'''
pass
cpdef onKey(self, int key, int action):
'''
Callback on key press or relase.
'''
pass
cpdef onChar(self, ch):
'''
Callback non-special key pressed
'''
pass
cpdef onFocus(self, int status):
'''
Callback on windows focus change
'''
pass
cpdef onEnter(self, int status):
'''
Callback on mouse pointer enter/leave event
'''
pass
cpdef onScroll(self, double dx, double dy):
'''
Callback on mouse scroll wheel
'''
pass
cpdef onIconify(self, int status):
'''
Callback on iconify status change
'''
pass
cpdef bint onClose(self):
'''
Callback on close request.
'''
return False
# callback functions

View file

@ -3,6 +3,9 @@
# This file is part of gltools - See LICENSE.txt
#
cdef class ShaderProgram:
'''
Class to encapsulate compiled GLSL shaders
'''
def __init__(self):
if not isGLExtLoaded:
raise GLError('OpenGL 2.1 function pointers not found')
@ -22,39 +25,66 @@ cdef class ShaderProgram:
return "()"
cpdef bint isValid(self):
'''
Return status
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
return prog.isValid()
cpdef begin(self):
'''
Set program as current
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
prog.begin()
cpdef end(self):
'''
Unset program. This will enable the fixed openGL pipeline
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
prog.end()
cpdef loadUniform1i(self, char *name, int value):
'''
Load named uniform integer value
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform1i(name, value):
raise GLError(errorMessage)
cpdef loadUniform1f(self, char *name, float value):
'''
Load named uniform float value
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform1f(name, value):
raise GLError(errorMessage)
cpdef loadUniform4f(self, char *name, float v0, float v1, float v2, float v3):
print name, v0, v1, v2, v3
'''
Load named uniform float vector
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform4f(name, v0, v1, v2, v3):
raise GLError(errorMessage)
cpdef loadUniformMatrix4vf(self, char *name, float [::1] value, int count = 1):
'''
Load named uniform matrix value
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniformMatrix4vf(name, &value[0], count):
raise GLError(errorMessage)
cpdef build(self, vertex_src = None, fragment_src = None):
'''
Compile program source. If no argument is given the
default program simulating the fixed pipeline is
loaded.
Raises GLError if failed.
'''
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
cdef int ret

View file

@ -3,10 +3,21 @@
# This file is part of gltools - See LICENSE.txt
#
cpdef BeginText():
'''
Start text drawing
'''
if not c_beginText():
raise GLError(errorMessage)
cpdef float DrawText(size, float x, float y, text):
'''
Draw text
:size: font size
:x: x coordinate
:y: y coordinate
:text: text (must encode to UTF-8)
'''
cdef float dx
cdef char *c_str
@ -19,5 +30,9 @@ cpdef float DrawText(size, float x, float y, text):
return dx
cpdef EndText():
'''
Finish text drawing. This will flush any pending text
drawing operations.
'''
if not c_endText():
raise GLError(errorMessage)

View file

@ -2,6 +2,9 @@
from imguiLib cimport *
cdef class UI:
'''
Draw UI elements
'''
def __init__(self):
self.scrollIdx = 0
imguiRenderGLInit()
@ -10,13 +13,22 @@ cdef class UI:
raise GLError(errorMessage)
cpdef bint anyActive(self):
'''
Return true if any ui element is active
'''
return imguiAnyActive()
cpdef flush(self):
'''
Flush drawing pipeline
'''
self.scrollIdx = 0
imguiRenderGLDraw()
cpdef beginFrame(self, int mx, int my, char mbut, int scroll):
'''
Start frame
'''
if mbut == GLFW_MOUSE_BUTTON_LEFT:
mbut = IMGUI_MBUT_LEFT
elif mbut == GLFW_MOUSE_BUTTON_RIGHT:
@ -27,9 +39,17 @@ cdef class UI:
imguiBeginFrame(mx, my, mbut, scroll)
cpdef endFrame(self):
'''
End frame
'''
imguiEndFrame()
cpdef bint beginScrollArea(self, name, int x, int y, int w, int h):
'''
Begin scroll area
Up to 10 scroll areas can be used, but not nested.
'''
cdef char *c_name
cdef bint ret
@ -44,21 +64,39 @@ cdef class UI:
return ret
cpdef endScrollArea(self):
'''
End scroll area
'''
imguiEndScrollArea()
cpdef indent(self):
'''
Indent current x position
'''
imguiIndent()
cpdef unindent(self):
'''
Unindent current x position
'''
imguiUnindent()
cpdef separator(self):
'''
Add horisontal separator space
'''
imguiSeparator()
cpdef separatorLine(self):
'''
Add horisontal separator line
'''
imguiSeparatorLine()
cpdef bint button(self, text, bint enabled):
'''
Button element
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -67,6 +105,9 @@ cdef class UI:
return imguiButton(c_text, enabled)
cpdef bint item(self, text, bint enabled):
'''
Item element
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -76,6 +117,9 @@ cdef class UI:
cpdef bint check(self, text, bint checked, bint enabled):
'''
Check box element
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -85,6 +129,9 @@ cdef class UI:
cpdef bint collapse(self, text, char* subtext, bint checked, bint enabled):
'''
Collapse element
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -93,6 +140,9 @@ cdef class UI:
return imguiCollapse(c_text, subtext, checked, enabled)
cpdef label(self, text):
'''
Text label (left aligned)
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -101,6 +151,9 @@ cdef class UI:
imguiLabel(c_text)
cpdef value(self, text):
'''
Text label (right aligned)
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -110,6 +163,9 @@ cdef class UI:
cpdef float slider(self, text, float val, float vmin, float vmax,
float vinc, bint enabled):
'''
Horisontal slider
'''
cdef float c_val = val
cdef char *c_text
@ -120,6 +176,9 @@ cdef class UI:
return c_val
cpdef drawText(self, int x, int y, int align, text, ColorRGBA color):
'''
Draw text
'''
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
@ -129,11 +188,20 @@ cdef class UI:
cpdef drawLine(self, float x0, float y0, float x1, float y1, float r, ColorRGBA color):
'''
Draw single line
'''
imguiDrawLine(x0, y0, x1, y1, r, color.toInt())
cpdef drawRoundedRect(self, float x, float y, float w, float h, float r, ColorRGBA color):
'''
Draw rounded rectangle
'''
imguiDrawRoundedRect(x, y, w, h, r, color.toInt())
cpdef drawRect(self, float x, float y, float w, float h, ColorRGBA color):
'''
Draw rectangle
'''
imguiDrawRect(x, y, w, h, color.toInt())

34
gltools/setup_docs.py Normal file
View file

@ -0,0 +1,34 @@
#!/usr/bin/python2
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
import sys
import os
from distutils.core import setup
from sphinx.setup_command import BuildDoc
cmdclass = {'build_sphinx': BuildDoc}
name = 'gltools'
version = '0.1'
release = '0.1.0'
try:
setup(
name=name,
author='Runar Tenfjord',
version=release,
cmdclass=cmdclass,
command_options={
'build_sphinx': {
'builder': ('setup_docs.py', 'html'),
}
},
)
except:
print('Traceback\n:%s\n' % str(sys.exc_info()[-2]))
sys.exit(1)
else:
print('\n')