From 842cf85d4b2a05803f110c501a101af7689b7bee Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 26 Dec 2011 21:56:24 +0000 Subject: [PATCH] Rebuild python tutorial with recent versions of tools. This will make further changes less noisy and also happens to fix the misparse of `__main__`. [SVN r76196] --- doc/tutorial/doc/html/index.html | 24 +++--- doc/tutorial/doc/html/python/embedding.html | 56 +++++++------ doc/tutorial/doc/html/python/exception.html | 4 +- doc/tutorial/doc/html/python/exposing.html | 84 ++++++++------------ doc/tutorial/doc/html/python/functions.html | 56 ++++++------- doc/tutorial/doc/html/python/hello.html | 22 ++--- doc/tutorial/doc/html/python/iterators.html | 38 +++------ doc/tutorial/doc/html/python/object.html | 48 +++++------ doc/tutorial/doc/html/python/techniques.html | 50 +++++------- 9 files changed, 162 insertions(+), 220 deletions(-) diff --git a/doc/tutorial/doc/html/index.html b/doc/tutorial/doc/html/index.html index 6e43c390..175ffe68 100644 --- a/doc/tutorial/doc/html/index.html +++ b/doc/tutorial/doc/html/index.html @@ -3,7 +3,7 @@ Chapter 1. python 2.0 - + @@ -31,7 +31,7 @@
-

+

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt ) @@ -42,8 +42,8 @@

Table of Contents

QuickStart
-
Building Hello World
-
Exposing Classes
+
Building Hello World
+
Exposing Classes
Constructors
Class Data Members
@@ -60,7 +60,7 @@
Default Arguments
Auto-Overloading
-
Object Interface
+
Object Interface
Basic Interface
Derived Object types
@@ -70,8 +70,8 @@
Embedding
Using the interpreter
Iterators
-
Exception Translation
-
General Techniques
+
Exception Translation
+
General Techniques
Creating Packages
Extending Wrapped Objects in Python
@@ -93,8 +93,8 @@ code takes on the look of a kind of declarative interface definition language (IDL).

-

- +

+ Hello World

@@ -121,14 +121,10 @@ That's it. We're done. We can now build this as a shared library. The resulting DLL is now visible to Python. Here's a sample Python session:

-

-

>>> import hello_ext
 >>> print hello_ext.greet()
 hello, world
 
-

-

Next stop... Building your Hello World module from start to finish... @@ -136,7 +132,7 @@

- +

Last revised: July 01, 2010 at 21:56:58 GMT

Last revised: December 26, 2011 at 21:51:27 GMT


diff --git a/doc/tutorial/doc/html/python/embedding.html b/doc/tutorial/doc/html/python/embedding.html index 5a590628..4e1c2185 100644 --- a/doc/tutorial/doc/html/python/embedding.html +++ b/doc/tutorial/doc/html/python/embedding.html @@ -3,7 +3,7 @@ Embedding - + @@ -39,8 +39,8 @@ a lot easier and, in a future version, it may become unnecessary to touch the Python/C API at all. So stay tuned... smiley

-

- +

+ Building embedded programs

@@ -81,8 +81,8 @@ exe embedded_program # name of the executable <library-path>$(PYTHON_LIB_PATH) <find-library>$(PYTHON_EMBEDDED_LIBRARY) ; -

- +

+ Getting started

@@ -95,8 +95,7 @@ exe embedded_program # name of the executable

  • Call Py_Initialize() - to start the interpreter and create the _main_ - module. + to start the interpreter and create the __main__ module.
  • Call other Python C API routines to use the interpreter. @@ -132,8 +131,8 @@ exe embedded_program # name of the executable and object class templates to automate the process.

    -

    - +

    + Running Python code

    @@ -152,8 +151,7 @@ exe embedded_program # name of the executable The globals and locals parameters are Python dictionaries containing the globals and locals of the context in which to run the code. For most intents and purposes you can use the namespace - dictionary of the _main_ - module for both parameters. + dictionary of the __main__ module for both parameters.

    Boost.python provides a function to import a module: @@ -165,8 +163,8 @@ exe embedded_program # name of the executable first), and returns it.

    - Let's import the _main_ - module and run some Python code in its namespace: + Let's import the __main__ module and run some Python code + in its namespace:

    object main_module = import("__main__");
     object main_namespace = main_module.attr("__dict__");
    @@ -180,8 +178,8 @@ exe embedded_program # name of the executable
             This should create a file called 'hello.txt' in the current directory containing
             a phrase that is well-known in programming circles.
           

    -

    - +

    + Manipulating Python objects

    @@ -197,16 +195,16 @@ exe embedded_program # name of the executable int five_squared = extract<int>(main_namespace["result"]);

    - Here we create a dictionary object for the _main_ - module's namespace. Then we assign 5 squared to the result variable and read - this variable from the dictionary. Another way to achieve the same result - is to use eval instead, which returns the result directly: + Here we create a dictionary object for the __main__ module's + namespace. Then we assign 5 squared to the result variable and read this + variable from the dictionary. Another way to achieve the same result is to + use eval instead, which returns the result directly:

    object result = eval("5 ** 2");
     int five_squared = extract<int>(result);
     
    -

    - +

    + Exception handling

    @@ -216,13 +214,13 @@ exe embedded_program # name of the executable

    try
     {
         object result = eval("5/0");
    -    // execution will never get here:
    -    int five_divided_by_zero = extract<int>(result);
    +    // execution will never get here:
    +    int five_divided_by_zero = extract<int>(result);
     }
     catch(error_already_set const &)
     {
    -    // handle the exception in some way
    -}
    +    // handle the exception in some way
    +}
     

    The error_already_set exception class doesn't carry any @@ -238,12 +236,12 @@ exe embedded_program # name of the executable { if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { - // handle ZeroDivisionError specially - } + // handle ZeroDivisionError specially + } else { - // print all other errors to stderr - PyErr_Print(); + // print all other errors to stderr + PyErr_Print(); } } diff --git a/doc/tutorial/doc/html/python/exception.html b/doc/tutorial/doc/html/python/exception.html index bf5953f3..7c053a7e 100644 --- a/doc/tutorial/doc/html/python/exception.html +++ b/doc/tutorial/doc/html/python/exception.html @@ -3,7 +3,7 @@ Exception Translation - + @@ -24,7 +24,7 @@

  • - Exception Translation

    +Exception Translation

    All C++ exceptions must be caught at the boundary with Python code. This boundary is the point where C++ meets Python. Boost.Python provides a default exception diff --git a/doc/tutorial/doc/html/python/exposing.html b/doc/tutorial/doc/html/python/exposing.html index 82eb649b..5547b2f2 100644 --- a/doc/tutorial/doc/html/python/exposing.html +++ b/doc/tutorial/doc/html/python/exposing.html @@ -3,7 +3,7 @@ Exposing Classes - + @@ -24,7 +24,7 @@

    - Exposing Classes

    +Exposing Classes
    Constructors
    Class Data Members
    @@ -67,8 +67,6 @@ we may use our class World in Python. Here's a sample Python session:

    -

    -

    >>> import hello
     >>> planet = hello.World()
     >>> planet.set('howdy')
    @@ -90,12 +88,10 @@
             We may wish to wrap a class with a non-default constructor. Let us build
             on our previous example:
           

    -

    -

    struct World
     {
    -    World(std::string msg): msg(msg) {} // added constructor
    -    void set(std::string msg) { this->msg = msg; }
    +    World(std::string msg): msg(msg) {} // added constructor
    +    void set(std::string msg) { this->msg = msg; }
         std::string greet() { return msg; }
         std::string msg;
     };
    @@ -120,7 +116,7 @@
     

    init<std::string>() exposes the constructor taking in a std::string (in Python, constructors are spelled - ""_init_""). + ""__init__"").

    We can expose additional constructors by passing more init<...>s @@ -140,8 +136,8 @@

    class_<Abstract>("Abstract", no_init)
     

    - This actually adds an _init_ - method which always raises a Python RuntimeError exception. + This actually adds an __init__ method which always raises + a Python RuntimeError exception.

    @@ -172,8 +168,6 @@ Then, in Python, assuming we have placed our Var class inside the namespace hello as we did before:

    -

    -

    >>> x = hello.Var('pi')
     >>> x.value = 3.14
     >>> print x.name, 'is around', x.value
    @@ -183,8 +177,8 @@
             Note that name is exposed as read-only
             while value is exposed as read-write.
           

    -
    >>> x.name = 'e' # can't change name
    -Traceback (most recent call last):
    +
    >>> x.name = 'e' # can't change name
    +Traceback (most recent call last):
       File "<stdin>", line 1, in ?
     AttributeError: can't set attribute
     
    @@ -198,8 +192,6 @@ The only way to access the class' data is through access (getter/setter) functions. Access functions expose class properties. Here's an example:

    -

    -

    struct Num
     {
         Num();
    @@ -221,21 +213,17 @@
     

    And at last, in Python:

    -

    -

    >>> x = Num()
     >>> x.value = 3.14
     >>> x.value, x.rovalue
     (3.14, 3.14)
    ->>> x.rovalue = 2.17 # error!
    -
    +>>> x.rovalue = 2.17 # error! +

    Take note that the class property rovalue is exposed as read-only since the rovalue setter member function is not passed in:

    -

    -

    .add_property("rovalue", &Num::get)
     
    @@ -310,8 +298,8 @@ is destroyed. We will see more of Boost.Python call policies later.

    -
    // Tell Python to take ownership of factory's result
    -def("factory", factory,
    +
    // Tell Python to take ownership of factory's result
    +def("factory", factory,
         return_value_policy<manage_new_object>());
     
    @@ -356,7 +344,7 @@ the job of wrapping classes that are meant to overridden in Python, easier.

    -

    - +

    + BOOST_PYTHON_FUNCTION_OVERLOADS

    @@ -424,8 +420,8 @@ Namespaces are one honking great idea -- let's do more of those!

    def("foo", foo, foo_overloads());
     
    -

    - +

    + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS

    @@ -467,8 +463,8 @@ Namespaces are one honking great idea -- let's do more of those! See the overloads reference for details.

    -

    - +

    + init and optional

    @@ -536,8 +532,8 @@ Namespaces are one honking great idea -- let's do more of those! Notice though that we have a situation now where we have a minimum of zero (0) arguments and a maximum of 3 arguments.

    -

    - +

    + Manual Wrapping

    diff --git a/doc/tutorial/doc/html/python/hello.html b/doc/tutorial/doc/html/python/hello.html index 35fc56e0..b7857382 100644 --- a/doc/tutorial/doc/html/python/hello.html +++ b/doc/tutorial/doc/html/python/hello.html @@ -3,7 +3,7 @@ Building Hello World - + @@ -24,9 +24,9 @@

    - Building Hello World

    -

    - +Building Hello World

    +

    + From Start To Finish

    @@ -91,8 +91,8 @@ in the command line. Pre-built Boost.Jam executables are available for most platforms. The complete list of Bjam executables can be found here.

    -

    - +

    + Let's Jam!

    @@ -107,8 +107,8 @@ The comments contained in the Jamrules file above should be sufficient to get you going.

    -

    - +

    + Running bjam

    @@ -133,12 +133,12 @@ using msvc : 8.0 ; # Python configuration -using python : 2.4 : C:/dev/toolsPython ; +using python : 2.4 : C:dev/tools/Python ;

    The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools. The second rule provides information on Python, its version and where it is - located. The above assumes that the Python installation is in C:/dev/tools/Python/. + located. The above assumes that the Python installation is in C:dev/tools\/Python. If you have one fairly "standard" python installation for your platform, you might not need to do this.

    @@ -165,7 +165,7 @@ bjam And so on... Finally:

    Creating library path-to-boost_python.dll
    -   Creating library path-to-'''hello_ext'''.exp
    +   Creating library /path-to-hello_ext.exp/
     **passed** ... hello.test
     ...updated 35 targets...
     
    diff --git a/doc/tutorial/doc/html/python/iterators.html b/doc/tutorial/doc/html/python/iterators.html index 3f87ab77..9fb402b6 100644 --- a/doc/tutorial/doc/html/python/iterators.html +++ b/doc/tutorial/doc/html/python/iterators.html @@ -3,7 +3,7 @@ Iterators - + @@ -62,22 +62,18 @@ The typical Python iteration protocol: for y in x... is as follows:

    -

    -

    -
    iter = x.__iter__()         # get iterator
    -try:
    +
    iter = x.__iter__()         # get iterator
    +try:
         while 1:
    -    y = iter.next()         # get each item
    -    ...                     # process y
    -except StopIteration: pass  # iterator exhausted
    -
    + y = iter.next() # get each item + ... # process y +except StopIteration: pass # iterator exhausted +

    Boost.Python provides some mechanisms to make C++ iterators play along nicely as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that is compatible with the Python iteration protocol. For example:

    -

    -

    object get_iterator = iterator<vector<int> >();
     object iter = get_iterator(v);
     object first = iter.next();
    @@ -129,8 +125,6 @@
           Let's put this into action... Here's an example from some hypothetical bogon
           Particle accelerator code:
         

    -

    -

    f = Field()
     for x in f.pions:
         smash(x)
    @@ -140,8 +134,6 @@
     

    Now, our C++ Wrapper:

    -

    -

    class_<F>("Field")
         .property("pions", range(&F::p_begin, &F::p_end))
         .property("bogons", range(&F::b_begin, &F::b_end));
    @@ -156,27 +148,23 @@
           a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>.
           Consider how we might implement a function that exposes std::list<int>::assign() to Python:
         

    -

    -

    template<typename T>
     void list_assign(std::list<T>& l, object o) {
    -    // Turn a Python sequence into an STL input range
    -    stl_input_iterator<T> begin(o), end;
    +    // Turn a Python sequence into an STL input range
    +    stl_input_iterator<T> begin(o), end;
         l.assign(begin, end);
     }
     
    -// Part of the wrapper for list<int>
    -class_<std::list<int> >("list_int")
    +// Part of the wrapper for list<int>
    +class_<std::list<int> >("list_int")
         .def("assign", &list_assign<int>)
    -    // ...
    -    ;
    +    // ...
    +    ;
     

    Now in Python, we can assign any integer sequence to list_int objects:

    -

    -

    x = list_int();
     x.assign([1,2,3,4,5])
     
    diff --git a/doc/tutorial/doc/html/python/object.html b/doc/tutorial/doc/html/python/object.html index d1cc7138..e05c47ec 100644 --- a/doc/tutorial/doc/html/python/object.html +++ b/doc/tutorial/doc/html/python/object.html @@ -3,7 +3,7 @@ Object Interface - + @@ -24,7 +24,7 @@

    - Object Interface

    +Object Interface
    Basic Interface
    Derived Object types
    @@ -60,8 +60,6 @@

    To illustrate, this Python code snippet:

    -

    -

    def f(x, y):
          if (y == 'foo'):
              x[3:7] = 'bar'
    @@ -75,8 +73,6 @@
     

    Can be rewritten in C++ using Boost.Python facilities this way:

    -

    -

    object f(object x, object y) {
          if (y == "foo")
              x.slice(3,7) = "bar";
    @@ -147,9 +143,9 @@
           

    void f(str name)
     {
    -    object n2 = name.attr("upper")();   // NAME = name.upper()
    -    str NAME = name.upper();            // better
    -    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
    +    object n2 = name.attr("upper")();   // NAME = name.upper()
    +    str NAME = name.upper();            // better
    +    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
     }
     

    @@ -169,7 +165,7 @@ do that in std C++.

    @@ -299,8 +295,6 @@

    You can access those values in Python as

    -

    -

    >>> my_module.choice.red
     my_module.choice.red
     
    @@ -308,15 +302,13 @@ where my_module is the module where the enum is declared. You can also create a new scope around a class:

    -

    -

    scope in_X = class_<X>("X")
                     .def( ... )
                     .def( ... )
                 ;
     
    -// Expose X::nested as X.nested
    -enum_<X::nested>("nested")
    +// Expose X::nested as X.nested
    +enum_<X::nested>("nested")
         .value("red", red)
         .value("blue", blue)
         ;
    diff --git a/doc/tutorial/doc/html/python/techniques.html b/doc/tutorial/doc/html/python/techniques.html
    index 0764fcd4..34cfc444 100644
    --- a/doc/tutorial/doc/html/python/techniques.html
    +++ b/doc/tutorial/doc/html/python/techniques.html
    @@ -3,7 +3,7 @@
     
     General Techniques
     
    -
    +
     
     
     
    @@ -23,7 +23,7 @@
     

    - General Techniques

    +General Techniques
    Creating Packages
    Extending Wrapped Objects in Python
    @@ -62,8 +62,8 @@ him to write code like this:

    import sounds.filters
    -sounds.filters.echo(...) # echo is a C++ function
    -
    +sounds.filters.echo(...) # echo is a C++ function +

    The first step is to write the wrapping code. We have to export each module separately with Boost.Python, like this: @@ -124,8 +124,6 @@ into his PYTHONPATH and fire up the interpreter:

    -

    -

    >>> import sounds.io
     >>> import sounds.filters
     >>> sound = sounds.io.open('file.mp3')
    @@ -146,8 +144,6 @@
             If we want this flexibility, we will have to complicate our package hierarchy
             a little. First, we will have to change the name of the extension modules:
           

    -

    -

    /* file core.cpp */
     BOOST_PYTHON_MODULE(_core)
     {
    @@ -178,8 +174,6 @@
             to each one. But if we leave it that way, the user will have to access the
             functions in the core module with this syntax:
           

    -

    -

    >>> import sounds.core._core
     >>> sounds.core._core.foo(...)
     
    @@ -188,7 +182,7 @@ magic: everything that is brought to the __init__.py namespace can be accessed directly by the user. So, all we have to do is bring the entire namespace from _core.pyd to core/__init__.py. - So add this line of code to soundscore__init__.py: + So add this line of code to sounds/core/__init__.py:

    from _core import *
     
    @@ -216,7 +210,7 @@ return s

    - Next, we add this line to soundsfilters__init__.py: + Next, we add this line to sounds/filters/__init__.py:

    from echo_noise import echo_noise
     
    @@ -237,11 +231,11 @@

    >>> class C(object): pass
     >>>
    ->>> # a regular function
    ->>> def C_str(self): return 'A C instance!'
    +>>> # a regular function
    +>>> def C_str(self): return 'A C instance!'
     >>>
    ->>> # now we turn it in a member function
    ->>> C.__str__ = C_str
    +>>> # now we turn it in a member function
    +>>> C.__str__ = C_str
     >>>
     >>> c = C()
     >>> print c
    @@ -256,8 +250,6 @@
             We can do the same with classes that were wrapped with Boost.Python. Suppose
             we have a class point in C++:
           

    -

    -

    class point {...};
     
     BOOST_PYTHON_MODULE(_geom)
    @@ -269,16 +261,14 @@
             If we are using the technique from the previous session, Creating
             Packages, we can code directly into geom/__init__.py:
           

    -

    -

    from _geom import *
     
    -# a regular function
    -def point_str(self):
    +# a regular function
    +def point_str(self):
         return str((self.x, self.y))
     
    -# now we turn it into a member function
    -point.__str__ = point_str
    +# now we turn it into a member function
    +point.__str__ = point_str
     

    All point instances created from C++ will @@ -303,9 +293,9 @@ You can even add a little syntactic sugar with the use of metaclasses. Let's create a special metaclass that "injects" methods in other classes.

    -
    # The one Boost.Python uses for all wrapped classes.
    -# You can use here any class exported by Boost instead of "point"
    -BoostPythonMetaclass = point.__class__
    +
    # The one Boost.Python uses for all wrapped classes.
    +# You can use here any class exported by Boost instead of "point"
    +BoostPythonMetaclass = point.__class__
     
     class injector(object):
         class __metaclass__(BoostPythonMetaclass):
    @@ -316,8 +306,8 @@
                             setattr(b,k,v)
                 return type.__init__(self, name, bases, dict)
     
    -# inject some methods in the point foo
    -class more_point(injector, point):
    +# inject some methods in the point foo
    +class more_point(injector, point):
         def __repr__(self):
             return 'Point(x=%s, y=%s)' % (self.x, self.y)
         def foo(self):
    @@ -355,8 +345,6 @@
             can easily become too high. If this is causing you problems, you can split
             the class_ definitions in multiple files:
           

    -

    -

    /* file point.cpp */
     #include <point.h>
     #include <boost/python.hpp>