Differences between revisions 2 and 29 (spanning 27 versions)
Revision 2 as of 2007-10-18 21:04:01
Size: 73693
Editor: DaveKuhlman
Comment:
Revision 29 as of 2014-05-17 15:44:11
Size: 7924
Editor: AMadera
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
#format rst

=====================
Jython Course Outline
=====================

:Author: Dave Kuhlman
:address: dkuhlman@rexx.com
    http://www.rexx.com/~dkuhlman

:revision: 1.1a
:date: Oct. 18, 2007

:copyright: Copyright (c) 2006 Dave Kuhlman. All Rights Reserved.
    This software is subject to the provisions of the MIT License
    http://www.opensource.org/licenses/mit-license.php.

:abstract: This document provides an outline of an introductory
    course on programming in Jython and connecting Jython to Java

.. sectnum::

.. contents::



How-to Write Jython Code
========================

Jython is Python. That's one of its big advantages: you get two for
the price of one. If your learn Python, then you have also learned
Jython, and vice versa. If you already know Python, then you know
Jython.

But, if you do know know Python **or** Jython, then here are good
training aids:

- `Python documentation --
  http://python.org/doc/
  <http://python.org/doc/>`_

- `Python tutorial --
  http://docs.python.org/tut/tut.html
  <http://docs.python.org/tut/tut.html>`_

- `BeginnersGuide/NonProgrammers --
  http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
  <http://wiki.python.org/moin/BeginnersGuide/NonProgrammers>`_

- `BeginnersGuide/Programmers --
  http://wiki.python.org/moin/BeginnersGuide/Programmers
  <http://wiki.python.org/moin/BeginnersGuide/Programmers>`_




Installing and Running Jython
=============================

Install Jython
--------------

You will need Java installed, of course. And, since you are likely to
want to use Jython class libraries from Jython, it is also likely that
you will want the Java SDK. **Important**: If more than one version
of Java is installed on your machine, make sure that when you install
Jython using the version of Java for which the SDK is installed and
the version of Java that you will be using when you run Jython.

Download the Jython installation jar file -- You can file the Jython
distribution here: `Jython downloads --
http://jython.org/Project/download.html
<http://jython.org/Project/download.html>`_.

Install Jython -- Follow the instructions at:
`Jython installation --
http://jython.org/Project/installation.html
<http://jython.org/Project/installation.html>`_::

    $ java -jar jython_installer-2.2.jar

Command line history -- On MS Windows, command line history for the
Jython interactive interpreter comes built-in. On Linux,
to get command line history, command line editing, and readline
support, follow the instructions here:
`ReadlineSetup --
http://wiki.python.org/jython/ReadlineSetup
<http://wiki.python.org/jython/ReadlineSetup>`_.



Configuration
-------------

There are several places to configure Jython.

Command-line options
~~~~~~~~~~~~~~~~~~~~

To display the options for ``jython``, type::

    $ jython --help



Jython configuration files
~~~~~~~~~~~~~~~~~~~~~~~~~~

For explanation of configuration options and values, see:

- The comments in the (default) registry file.

- `The Jython Registry --
  http://www.jython.org/docs/registry.html
  <http://www.jython.org/docs/registry.html>`_.


Checking configuration values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From within the Jython interactive interpreter or from within your
Jython application, you can display the values of configuration
properties.

To get the system properties as a dictionary-like object, do::

    >>> from java.lang import System
    >>> props = System.getProperties()

Of particular interest are the following:

- ``props['java.class.path']`` -- Location of the Jython jar file.

- ``props['java.library.path']`` -- Locations of Java class libraries.

Other properties are in sys.registry::

    >>> import sys
    >>> r = sys.registry
    >>> for k in r:
    ... print k, r[k]

Here is a script that you may find useful when interactively
inspecting system properties::

    >>> from java.lang import System
    >>> props = System.getProperties()
    >>> names = []
    >>> for name in props.keys():
    ... names.append(name)
    ...
    >>> names.sort() # now you can list the keys in alpha order
    >>> for val in props['java.class.path'].split(':'):
    ... print val
    ...
    /home/dkuhlman/a1/Python/Jython/Tmp1/Jython-2.1/jython.jar
    /usr/share/jython/jython.jar


Classpath and python path
~~~~~~~~~~~~~~~~~~~~~~~~~

Jython can pick up Java class files from locations on either the
Jython/Python path (see ``sys.path``) or the Java classpath. Set
these with the following:

- The Python/Jython path can be set in your registry file. See
  registry variable ``python.path``.

  Or, at runtime, you could do::

      >>> import sys
      >>> sys.path.append('/path/to/module')

  But, you must do the above *before* trying to import the module.

- Set the classpath by setting the CLASSPATH environment variable.
  Note that (on my Linux machine, at least) the CLASSPATH environment
  variable is picked up and added to the Java ``-classpath`` flag.

A few rules about CLASSPATH and python.path:

- ``sys.path`` in the registry file -- Add here to enable importing
  from Java classes (.java), Java class libraries (.jar), and
  Jython/Python (.py).

- CLASSPATH -- Add paths to this environment variable in order to
  enable importing from Java classes (.java) and Java class
  libraries (.jar), but not Jython/Python (.py).


Running Jython
--------------

The Jython interactive, command-line interpreter: ``jython``.

Jython IDEs (interactive development environments) -- There is a
Jython plug-in for Eclipse. See: http://pydev.sourceforge.net/.

Exercises -- Start the Jython interpreter. Then do each of the
following:

- Print "hello".

- Define an empty class.

- Import a Python/Jython file containing a class definition.
  Create an instance of that class.

- Import a module from the standard Python/Jython library, for
  example, ``re`` or ``os.path``. Use a method from that module.

- Import a Java class, for example, ``java.util.Vector``. Create
  and use an instance of that class.

Running Jython scripts:

- From the command line, run a script with ``jython``. For
  example::

      $ jython myscript.py

- For help, run::

      $ jython --help

- For debugging, use something similar to the following::

      import pdb
      pdb.run('main()')

  Or::

      import pdb
      pdb.set_trace()

  For example::

      def main():
          util101()

      if __name__ == '__main__':
          import pdb; pdb.set_trace()
          main()

- To "set a breakpoint" in your code so that it will drop into
  debugger, either (1) use the ``b`` command at the ``pdb`` prompt
  or (2) add the following to your code at the location where you
  wish to drop into the debugger::

      import pdb; pdb.set_trace()

  For more information on the Python debugger, see `The Python
  Debugger <http://docs.python.org/lib/module-pdb.html>`_ in the
  Python standard documentation, or while in the debugger, type
  ``help``.

- To make a script both "run-able" and "import-able", use the
  following idiom::

      if __name__ == '__main__':
          main()

Don't forget to include a doc string at the top of your module for
documentation.

Exercise -- Create a small Jython script:

- Include a class in your script that creates an instance of
  ``java.util.Vector``.

- Make the script both "run-able" and "import-able".

- From the Jython interpreter, import the script and create an instance
  of the class.

- From the command line, use ``jython`` to run the script.

- Add ``pdb`` debugging to your script. Run the script again from
  the command line. Step through several lines of code.


Installing Jython/Python packages
---------------------------------

Some Jython packages will be distributed as a Java jar file. If that
is the case, add the jar file to your classpath.

If the package is distributed as a standard Python package with a
``setup.py`` installer file and *if* there are no C/C++ files in the
package, then you might try something like the following::

    $ python setup.py install --prefix /path/to/install/directory

And, then put that install directory on your classpath.



Intergrating Java into Jython/Python
====================================

Calling existing Java code
--------------------------

In order to call Java code from Jython do the following:

1. Import the Java module.

2. Use the Java module to create an instance/object.

3. Call functions and objects in it.

It works the way you would hope and expect it to. Here is an
example::

    >>> from java.util import Vector
    >>> v = Vector()
    >>> dir(v)
    ['__init__', 'add', 'addAll', 'addElement', 'capacity', 'class', 'clear', 'clone', 'contains', 'containsAll', 'copyInto', 'elementAt', 'elements', 'empty', 'ensureCapacity', 'equals', 'firstElement', 'get', 'getClass', 'hashCode', 'indexOf', 'insertElementAt', 'isEmpty', 'iterator', 'lastElement', 'lastIndexOf', 'listIterator', 'notify', 'notifyAll', 'remove', 'removeAll', 'removeAllElements', 'removeElement', 'removeElementAt', 'retainAll', 'set', 'setElementAt', 'setSize', 'size', 'subList', 'toArray', 'toString', 'trimToSize', 'wait']
    >>>
    >>> v.add('aaa')
    1
    >>> v.add('bbb')
    1
    >>> for val in v:
    ... print val
    ...
    aaa
    bbb


In some cases you will need to pass Java objects to Java methods.

Special treatment for some overloaded Java methods -- Explicitly
create and pass Jython objects. For more on this, see:
`Overloaded Java Method Signatures
<http://www.jython.org/Project/userguide.html#overloaded-java-method-signatures>`_
-- http://www.jython.org/Project/userguide.html#overloaded-java-method-signatures.


Often you can use Python/Jython style and idioms to process Java
objects. For example: the Jython ``for`` statement can be applied
to Java collection objects.

Exercise -- Use the class ``java.util.Hashtable`` to create a
dictionary with several keys and values, then print out the keys
and their values. Solution::

    >>> from java.util import Hashtable
    >>> impl_language = Hashtable()
    >>> impl_language.put('jython', 'java')
    >>> impl_language.put('python', 'c')
    >>> for key in impl_language.keys():
    ... print '%s is implemented in %s' % (key, impl_language[key])
    ...
    python is implemented in c
    jython is implemented in java


Extending a Java class in Jython
--------------------------------

You can import and then extend (sub-class) a Java class.

Example -- This sample extends the Java filestream class by adding a
method that converts all characters to upper case:: ::

    import sys
    from java.io import FileOutputStream

    class UppercaseFileOutputStream(FileOutputStream):
        def write_upper(self, text):
            text = text.upper()
            self.write(text)

    def test(outfilename):
        fos = UppercaseFileOutputStream(outfilename)
        for idx in range(10):
            fos.write_upper('This is line # %d\n' % idx)
        fos.close()
        infile = open(outfilename, 'r')
        for line in infile:
            line = line.rstrip()
            print 'Line: %s' % line

    def main():
        args = sys.argv[1:]
        if len(args) != 1:
            print 'usage: extend_fileoutputstream.py <infilename>'
            sys.exit(1)
        test(args[0])

    if __name__ == '__main__':
        main()



Emulating Jython classes in Java
--------------------------------

You can make a Java class "act like" one of the built-in Jython
classes. In order to do so, you would implement one or more of
Jython's special methods. You can find descriptions of the special
methods in the "Python Reference Manual":
`3.4 Special method names --
http://docs.python.org/ref/specialnames.html
<http://docs.python.org/ref/specialnames.html>`_.

Example: This module implements a class that acts like a sequence in
certain ways, specifically (1) it responds to the ``len()`` operator
by returning a length; (2) it supports an ``append`` method; and (3)
it supports the use of the ``[]`` operator to get a value::

    import java.util.Vector;

    // Implement selected part of the Jython container interface.
    public class CustomContainer {

        private Vector data;

        public CustomContainer() {
            data = new Vector();
        }

        // Implement the len() operator.
        public int __len__() {
            return data.size();
        }

        // Implement the append() method.
        public int append(String item) {
            data.add(item);
            return 1;
        }

        // Implement the [] operator.
        public String __getitem__(int index) {
            return (String)data.elementAt(index);
        }
    }


And here is an example of the use of this custom container class::

    $ jython
    Jython 2.2.1rc1 on java1.4.2_10
    Type "copyright", "credits" or "license" for more information.
    >>>
    >>> import CustomContainer as cc
    >>> container = cc()
    >>> container.append('item number one')
    1
    >>> container.append('item number two')
    1
    >>> container.append('item number three')
    1
    >>> len(container)
    3
    >>> for index in range(len(container)):
    ... print container[index]
    ...
    item number one
    item number two
    item number three

Notes:

- A more powerful solution, depending on your needs, would be for
  ``CustomContainer`` to inherit from ``java.util.Vector``. See
  section `Emulating Jython Dictionaries, Sequences, Etc.`_ for an
  example.



Preparing Java code to be called from Jython
--------------------------------------------

Another view: Java is the extension language for Jython.

No special work is required. Jython can call normal Java classes.

Need to pay attention to data types, for example, on the Jython
side. Use an explicit cast, for example, ``float(5)``.

For additional help, see:

- `Overview of Jython Documentation <http://www.jython.org/docs/index.html>`_

- The Jython API
  `with frames <http://www.jython.org/docs/javadoc/index.html>`_ or
  `without frames <http://www.jython.org/docs/javadoc/overview-summary.html>`_.

You can also customize a Java class to make it more "Jythonic".


Adding doc strings to a Java class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This first, simple example adds doc strings::

    // Showme.java

    import org.python.core.*;

    public class ShowMe
    {
        public static PyString __doc__ =
            new PyString("Simple Jython extension #1");

        public String name;

        public ShowMe(String newName)
        {
            name = newName;
        }
        public static PyString __doc__set_name = new PyString(
            "Set the name attribute");
        public void set_name(String newName)
        {
            name = newName;
        }
        public static PyString __doc__get_name = new PyString(
            "Get the name attribute");
        public String get_name()
        {
            return name;
        }

        public static PyString __doc__Show = new PyString(
            "Show the name attribute");
        public void Show()
        {
            System.out.println("My name is \"" + name + "\".");
        }
    }


Notes:

- Doc strings for the class and methods are defined with public
  static Strings. You can, alternatively, use PyString.

- For more complex control over doc strings (for example, in a
  Java files that contains multiple classes) your class can
  implement the ``ClassDictInit`` interface and implement the
  ``classDictInit`` method. See "Jython for Java Programmers",
  pp. 276 ff.


Working with Jython arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``ArgParser`` class helps us handle Jython keyword arguments.
If helps us support the analog of Jython's ``*args`` and
``**kwargs`` in Java methods.

How to do it -- An overview:

1. Define your Java method with the following prototype::

       public PyObject foo(PyObject[] args, String[] keywords);

2. Parse the arguments with class ``ArgParser``.

3. Access individual arguments with ``ArgParser`` methods
   ``getInt()``, ``getString()``, ``getList()``, and
   ``getPyObject()``.

4. Since both ``args`` and ``keywords`` are arrays, check the
   number of arguments actually passed with ``args.length`` and
   ``keywords.length``.

For more information, see: `org.python.core Class ArgParser
<http://www.jython.org/docs/javadoc/org/python/core/ArgParser.html>`_.

Exercise -- (1) Write a Java class containing a method that
prints all its arguments and all the keyword arguments passed to
it. (2) Then call that method from Jython.

Solution::

    // DemoArgs.java

    import org.python.core.*;

    public class DemoArgs
    {
        public static PyString __doc__ =
            new PyString("Demonstrate the use of complex arguments.");

        public String name;
        public String value;

        public DemoArgs(String newName, String newValue)
        {
            name = newName;
            value = newValue;
        }

        public static PyString __doc__set_name = new PyString(
            "Set the name attribute");
        public void set_name(PyObject[] args, String[] kwargs)
        {
            System.out.println("length(args): " +
                String.valueOf(args.length) +
                " length(kwargs): " +
                String.valueOf(kwargs.length)
                );
            ArgParser ap = new ArgParser("set_name", args, kwargs,
                new String[] {"name", "value"});
            String newName = ap.getString(0, "");
            String newValue = ap.getString(1, "<empty>");
            if (newName.compareTo("") != 0)
            {
                name = newName;
            }
            value = newValue;
        }
        public static PyString __doc__get_name = new PyString(
            "Get the name attribute");
        public String get_name()
        {
            return name;
        }

        public static PyString __doc__get_value = new PyString(
            "Get the value attribute");
        public String get_value()
        {
            return value;
        }

        public static PyString __doc__Show = new PyString(
            "Show the name and value attributes");
        public void Show()
        {
            System.out.println("My name is \"" + name +
                "\" and my value is \"" + value + "\".");
        }
    }


Compile the above file with ``javac`` or some other Java compiler. To
do so, you will need to add ``jython.jar`` to your ``CLASSPATH``.

Notes:

- Use class ``ArgParser`` to capture the arguments.

- Use ``ArgParser`` methods ``getInt``, ``getString``,
  ``getPyObject``, and ``getList`` to retrieve arguments.

- Notice that in method ``get_name``, we print the length of the
  args and kwargs. This demonstrates that you can check the
  length of these arrays and can throw an exception if, for
  example, too few arguments are passed.

Also see the Jython FAQ:
`5.3 Supporting *args and **kw in Java methods --
http://jython.org/Project/userfaq.html#supporting-args-and-kw-in-java-methods
<http://jython.org/Project/userfaq.html#supporting-args-and-kw-in-java-methods>`_.


Sub-classing a Java class
~~~~~~~~~~~~~~~~~~~~~~~~~

Notice that, in Jython, we can extend a class written in Java::

    import DemoArgs

    class Fancy(DemoArgs):
        def __init__(self, name, value):
            DemoArgs.__init__(self, name, value)
        def ShowFancy(self):
            print "I'm fancy and my name is %s and my value is %s" % \
                (self.name, self.value)

    def test():
        f = Fancy('dave', 'funny')
        f.ShowFancy()
        f.set_name('daniel', 'cute')
        f.ShowFancy()

    test()

When you run the above, you should see something like the following::

    $ jython tmp.py
    I'm fancy and my name is dave and my value is funny
    length(args): 2 length(kwargs): 0
    I'm fancy and my name is daniel and my value is cute


Emulating Jython Dictionaries, Sequences, Etc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Extend class org.python.core.PyObject and its sub-classes. See:
`org.python.core Class PyObject
<http://www.jython.org/docs/javadoc/org/python/core/PyObject.html>`_.

Implement the following methods::

    __getitem__()
    __finditem()
    __setitem__()
    __delitem__()
    ...

``getitem()`` vs. ``finditem()``:

- If the index is not found or out of range, ``finditem()``
  returns null, whereas ``__getitem()`` should throw an exception.

- The Jython API documentation says to override ``finditem()`` and
  not ``getitem()``. See: `org.python.core Class PyObject
  <http://www.jython.org/docs/javadoc/org/python/core/PyObject.html>`_.

See
`3.3.5 Emulating container types --
http://docs.python.org/ref/sequence-types.html
<http://docs.python.org/ref/sequence-types.html>`_
in the Python
Reference Manual for more information on customizing dictionaries
and sequences.

Exercise -- (1) Write a Java class that emulates or imitates a
Jython dictionary. (2) In addition, each access method should
print a message. (3) Test your Java class from Jython by creating
an instance of it, then setting and retrieving a key-value pair.


Solution #1 -- Emulating a dictionary
+++++++++++++++++++++++++++++++++++++

This solution is for educational purposes only (see
`Solution #2 -- Extending PyDictionary`_)::

    // TestDict.java

    import org.python.core.*;
    import java.util.*;

    public class TestDict
    {
     public Hashtable data;
     
     public TestDict()
     {
      data = new Hashtable();
     }
     public void __setitem__(String key, String value)
     {
      data.put(key, value);
      System.out.println("Added key \"" + key + "\" value: \"" +
             value + "\"");
     }
     public String __getitem__(String key)
     {
      if (data.containsKey(key))
      {
       String value = (String)data.get(key);
       System.out.println("Found key \"" + key + "\" value: \"" +
             value + "\"");
       return value;
      }
      else
      {
       throw new PyException(Py.KeyError, "The key does not exit.");
      }
     }
     public boolean __contains__(String key)
     {
      if (data.containsKey(key))
      {
       System.out.println("Found key \"" + key + "\"");
       return true;
      }
      else
      {
       System.out.println("Did not find key \"" + key + "\"");
       return false;
      }
     }
    }

Notes:

- The above class implements a limited part of the Jython
  dictionary protocol, in particular ``__setitem__``,
  ``__getitem__``, and ``__contains__``.

- This above solution also illustrates how to throw ("raise" in
  Jython terms) an exception from Java that can be caught in
  Jython. Here is an example of catching that exception on the
  Jython side::

      >>> try:
      ... x = b['xyz']
      ... except KeyError, e:
      ... print '*** error: %s' % e
      ...
      *** error: The key does not exit.

- The Jython FAQ recommends that your Jython class extends
  PyObject. (see `5. Extending Jython --
  http://jython.org/Project/userfaq.html#extending-jython
  <http://jython.org/Project/userfaq.html#extending-jython>`_)
  I've found that it is not strictly necessary to extend ``PyObect``
  in your Java class (the one that emulates a Jython built-in).
  **But, if you do**, you will need to follow the signature of the
  methods that implement operators (for example ``__setitem__``,
  ``__getitem__``, etc) exactly. To learn those signatures, see the
  API documentation in the ``Doc/`` directory under your Jython
  installation.

Here is an example that uses the above solution::

    # test_TestDict.py

    import TestDict

    def test():
        d = TestDict()
        d['aa'] = 'AAAA'
        d['bb'] = 'BBBB'
        d['cc'] = 'CCCC'
        print d.data
        if 'bb' in d:
            print 'present'

    test()

And, here is the result of running this test::

    $ jython test_TestDict.py
    Added key "aa" value: "AAAA"
    Added key "bb" value: "BBBB"
    Added key "cc" value: "CCCC"
    {aa=AAAA, bb=BBBB, cc=CCCC}
    Found key "bb"
    present


Solution #2 -- Extending PyDictionary
+++++++++++++++++++++++++++++++++++++

This solution shows how you most likely would start if you wanted to
extend the dictionary type or implement a custom dictionary type::

    // TestDictSub.java

    import org.python.core.*;
    import java.util.*;

    public class TestDictSub extends PyDictionary
    {
        public void __setitem__(PyObject key, PyObject value)
        {
            super.__setitem__(key, value);
            System.out.println("Added key \"" + key + "\" value: \"" +
                               value + "\"");
        }
        public PyObject __getitem__(PyObject key)
        {
            if (super.has_key(key))
            {
                PyObject value = super.__getitem__(key);
                System.out.println("Found key \"" + key + "\" value: \"" +
                               value + "\"");
                return value;
            }
            else
            {
                throw new PyException(Py.KeyError, "The key does not exit.");
            }
        }
    }

Notes:

- This class inherits the methods in the PyDictionary class. It
  overrides several of those methods, specifically ``__setitem__``
  and ``__getitem__``.

- The Java class could also extend the dictionary type by
  implementing additional, new methods.

Also see the Jython FAQ:
`5.1 Java classes that emulate Jython Dictionaries and Sequences --
http://jython.org/Project/userfaq.html#java-classes-that-emulate-jython-dictionaries-and-sequences
<http://jython.org/Project/userfaq.html#java-classes-that-emulate-jython-dictionaries-and-sequences>`_.



Emulating Jython object attribute access
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We can implement and override object attribute access in a Java
class:

Extend class org.python.core.PyObject and its sub-classes.

Implement the following methods::

    __findattr__()
    __setattr__()
    __delattr__()

``__findattr__()`` is called *only if* an attribute is not found
in an object.

Exercise -- (1) Write a Java class class that supports access to
attributes. (2) In addition, each access method should print a
message. (3) Test your Java class from Jython by creating an
instance of it, then setting and getting an attribute.

Solution::

    // TestDictSub.java

    import org.python.core.*;
    import java.util.*;

    public class TestDictAttr extends PyDictionary
    {
        public PyObject __findattr__(String key)
        {
            PyString objkey = new PyString(key);
            if (super.has_key(objkey))
            {
                PyObject value = super.__getitem__(objkey);
                System.out.println("Found attr \"" + key + "\" value: \"" +
                               value + "\"");
                return value;
            }
            else
            {
                throw new PyException(Py.KeyError, "The attr does not exit.");
            }
        }
    }

Notes:

- Test this solution with the following::

      $ jython
      Jython 2.2a1 on java1.4.2 (JIT: null)
      Type "copyright", "credits" or "license" for more information.
      >>>
      >>> import TestDictAttr
      >>> a = TestDictAttr()
      >>> print a.dave
      Traceback (innermost last):
        File "<console>", line 1, in ?
      KeyError: The attr does not exit.
      >>> a['dave'] = 'some little value'
      >>> print a.dave
      Found attr "dave" value: "some little value"
      some little value

- Arguments to ``__findattr__`` and ``__finditem__`` must be
  interned strings. Literal strings are automatically interned.
  For other strings, use ``intern(s)``.

Also see the Jython FAQ:
`5.2 Emulating Jython object attribute access with a Java class --
http://jython.org/Project/userfaq.html#emulating-jython-object-attribute-access-with-a-java-class
<http://jython.org/Project/userfaq.html#emulating-jython-object-attribute-access-with-a-java-class>`_.


Extending a built-in Jython class in Java
-----------------------------------------

In Java, you can inherit from an extend the built-in Jython classes.

Some of the classes that you can consider extending are:

- PyDictionary

- PyInteger

- PyList

- PyString

- PyStringMap

- PyTuple

An example that extends the ``PyDictionary`` class is in
section `Solution #2 -- Extending PyDictionary`_.


Integrating Jython/Python into Java
===================================

Calling Jython from Java
------------------------

Run Jython code on an interpreter embedded in Java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``jythonc`` is currently unsupported and is deprecated, although it
might reappear in some future version of Jython. So, using
``jythonc`` to compile your Jython code to Java for use in your Java
code may not appeal to you. An embedded Jython interpreter may be a
solution.

Overview -- Here is the general approach:

1. Create a Jython interpreter object.

2. Insert (set) values in your embedded interpreter, if needed.

3. Use that interpreter to either:

   1. Run several lines of code that import and use your Jython
      module, *or*

   2. Run a small wrapper script that imports and uses your Jython
      modules.

4. Retrieve values from your embedded interpreter, if necessary.

Each of these topics has been covered above.

Disadvantages of this approach:

- It's a little clumsy. Requires a small amount of Java code.

Advantages of this approach:

- ``jythonc`` is not required. ``jythonc`` is deprecated and is not
  planned for Jython 2.3.

- No need for a separate compile step.

- No need to *re-compile* your script each time it is modified.


How to run Jython code on an interpreter embedded in Java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Resources -- For instructions on how to call Jython code from Java,
see:

- `Accessing Jython from Java Without Using jythonc
  http://wiki.python.org/jython/JythonMonthly/Articles/September2006/1
  <http://wiki.python.org/jython/JythonMonthly/Articles/September2006/1>`_

- `Simple and Efficient Jython Object Factories
  http://wiki.python.org/jython/JythonMonthly/Articles/October2006/3
  <http://wiki.python.org/jython/JythonMonthly/Articles/October2006/3>`_
  -- Note that the example that follow was developed from this
  document.


Description -- In order to implement this approach, here is what
you will do:

- Implement one or more Jython/Python modules containing one or more
  classes.

- Create a Java interface for each Jython class that you want to
  expose to Java. The interface should describe each method that
  you wish to expose to Java.

- Create a single Java "factory" class:

  - The constructor (1) creates a Jython interpreter; (2) runs a
    script that imports the Jython modules containing the Jython
    classes; (3) retrieve and save the Jython classes from the
    intrepreter.

  - Implement one "createX" method for each Jython/Python class/type
    to be used from Java.

- Implement the Java code that uses the Jython classes: (1) create a
  factory object; (2) call the "createX" methods to create Java
  objects that give access to the Jython classes; (3) call the
  Jython methods through the Jython "proxies".

Example -- a possible organization on disk
++++++++++++++++++++++++++++++++++++++++++

::

    |-- Employee.py # The Jython classes
    |-- jyinterface
    | |-- Main.java # The client code
    | |-- factories
    | | |-- EmployeeFactory.java # The factory
    | `-- interfaces
    | |-- DependentType.java # The Java interface
    | `-- EmployeeType.java # The Java interface

Notes:

- The Jython classes (in this case, Employee.py) can go anywhere on
  your Jython/Python path. See ``python.path``.in your registry
  file: `The Jython Registry --
  http://jython.org/Project/userguide.html#the-jython-registry
  <http://jython.org/Project/userguide.html#the-jython-registry>`_.

- Layout for the Java code follows normal Java rules for packages.

Example -- the Jython classes
+++++++++++++++++++++++++++++

These are the Jython classes that we wish to expose to and call from
Java::

    # Employee.py

    from jyinterface.interfaces import EmployeeType
    from jyinterface.interfaces import DependentType


    class Employee(EmployeeType):
        def __init__(self, first, last, id):
            self.first = first
            self.last = last
            self.id = id
            deps = self.create_dependents()
            self.deps = deps

        def create_dependents(self):
            d1 = Dependent('Sally', 'Serious', 11)
            d2 = Dependent('Larry', 'Lighthearted', 12)
            return [d1, d2]

        def getEmployeeFirst(self):
            return self.first

        def getEmployeeLast(self):
            return self.last

        def getEmployeeId(self):
            return self.id

        def getDependents(self):
            return self.deps

        def addDependent(self, dependent):
            self.deps.append(dependent)


    class Dependent(DependentType):
        def __init__(self, first, last, id):
            self.first = first
            self.last = last
            self.id = id

        def getDependentFirst(self):
            return '<<%s>>' % self.first

        def getDependentLast(self):
            return '<<%s>>' % self.last

        def getDependentId(self):
            return self.id * 4


Example -- A Java interface class
+++++++++++++++++++++++++++++++++

This (jyinterface/interfaces/EmployeeType.java) describes the
interface to our Java (client) code::

    // EmployeeType.java

    package jyinterface.interfaces;
    import org.python.core.PyList;
    import jyinterface.interfaces.DependentType;


    public interface EmployeeType {
        public String getEmployeeFirst();
        public String getEmployeeLast();
        public String getEmployeeId();
        public PyList getDependents();
        public void addDependent(DependentType dependent);
    }


Example -- another interface class
++++++++++++++++++++++++++++++++++

This (jyinterface/interfaces/DependentType.java) is another
interface. It describes and helps to expose another Jython class.

::

    // DependentType.java

    package jyinterface.interfaces;

    public interface DependentType {
         public String getDependentFirst();
         public String getDependentLast();
         public Integer getDependentId();
    }

Notes:

- We only describe the portions of the interface that we wish to
  expose to Java. It is likely that this will be a proper subset of
  the methods in our Jython class.


Example -- the factory class
++++++++++++++++++++++++++++

This (jyinterface/factories/EmployeeFactory.java) is the factory
that creates (proxy) instances of our Jython classes. These
instances are Java instances with an underlying Jython
implementation::

    // EmployeeFactory.java

    package jyinterface.factory;

    import jyinterface.interfaces.EmployeeType;
    import jyinterface.interfaces.DependentType;
    import org.python.core.PyObject;
    import org.python.core.PyString;
    import org.python.core.PyInteger;
    import org.python.util.PythonInterpreter;

    public class EmployeeFactory {

        public EmployeeFactory() {
            String cmd = "from Employee import Employee\nfrom Employee import Dependent";
            PythonInterpreter interpreter = new PythonInterpreter();
            //interpreter.exec("from Employee import Employee");
            //interpreter.exec("from Employee import Dependent");
            interpreter.exec(cmd);
            jyEmployeeClass = interpreter.get("Employee");
            jyDependentClass = interpreter.get("Dependent");
        }

        public EmployeeType createEmployee(String first, String last, String id) {
            PyObject employeeObj = jyEmployeeClass.__call__(
                new PyString(first),
                new PyString(last),
                new PyString(id));
            return (EmployeeType)employeeObj.__tojava__(EmployeeType.class);
        }

        public DependentType createDependent(String first, String last, int id) {
            PyObject dependentObj = jyDependentClass.__call__(
                new PyString(first),
                new PyString(last),
                new PyInteger(id));
            return (DependentType)dependentObj.__tojava__(DependentType.class);
        }

        private PyObject jyEmployeeClass;
        private PyObject jyDependentClass;
    }

Notes:

- The Jython interpreter is created only once, when the factory
  object is created.

- The Java classes that are proxies for the Jython classes exposed
  to Java (jyEmployeeClass amd jyDependentClass) are also only
  created once.

- Each "creater" method (createEmployee and createDependent) uses
  the ``__call__`` method to create an instance. This is the same
  as using ``obj = Employee()``, for example, in Jython. Then the
  result is converted to a Java object and returned.

Example -- the Java consumer code
+++++++++++++++++++++++++++++++++

This (jyinterface/Main.java) is the Java code that uses our Jython
classes::

    // Main.java

    package jyinterface;

    import jyinterface.factories.EmployeeFactory;
    import jyinterface.interfaces.EmployeeType;
    import jyinterface.interfaces.DependentType;
    import org.python.core.PyObject;
    import org.python.core.PyList;

    public class Main {

        private static void printEmployee(EmployeeType employee) {
            System.out.println("Name: " + employee.getEmployeeFirst() + " "
                    + employee.getEmployeeLast());
            System.out.println("Id: " + employee.getEmployeeId());
            PyList deplist = employee.getDependents();
            int count = deplist.__len__();
            System.out.println("count: " + Integer.toString(count));
            for (int idx = 0; idx < count; idx++) {
                PyObject obj = deplist.__getitem__(idx);
                DependentType dep = (DependentType)obj.__tojava__(DependentType.class);
                printDependent(dep);
            }
        }

        private static void printDependent(DependentType dependent) {
            System.out.println("Dep Name: " + dependent.getDependentFirst() + " "
                    + dependent.getDependentLast());
            System.out.println("Dep Id: " + dependent.getDependentId().toString());
        }

        public static void main(String[] args) {
            EmployeeFactory factory = new EmployeeFactory();
            EmployeeType emp = factory.createEmployee("Josh", "Juneau", "1");
            printEmployee(emp);
            printEmployee(factory.createEmployee("Charlie", "Groves", "2"));
            System.out.println("------------------");
            DependentType dependent = factory.createDependent(
                "Dave", "Kuhlman", 4);
            printDependent(dependent);
            System.out.println("------------------");
            emp.addDependent(dependent);
            printEmployee(emp);
        }
    }


Notes:

- This client code creates a factory object, then uses that factory
  object to create several Java objects that are proxies for the
  Jython Employee and Dependent objects.

- Then the client code calls several of the methods that are
  implemented in the Jython code and exposed to Java through the
  Java interfaces.

- On the Java side, we apply operators to a list object (and other
  Jython built-in types) by calling their methods directly, for
  example:

  - ``len()`` -- ``obj.__len__()``

  - ``obj[idx]`` -- ``obj.__getitem__(idx)``

  For descriptions of these "special" methods, see the following
  section in the Python language reference:
  `3.4 Special method names --
  http://docs.python.org/ref/specialnames.html
  <http://docs.python.org/ref/specialnames.html>`_.

- On the Java side, we use a Jython object by

  1. Retrieving it as a generic ``PyObject``.

  2. Converting it to a Java object with::

         obj.__tojava__(XXType.class)

     where ``XXType`` is the Java interface that describes the
     Jython object.

  3. Casting the object to the appropriate Java type.

  4. Calling its "Java" methods.

- We can pass a Jython object back to Jython from Java. Notice the
  call to method ``addDependent()``.


Additional support for running Jython code on an interpreter embedded in Java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In what follows, we provide and describe scripts that assist in
using the above strategy.

- ``generate_interfaces.py`` -- Does some of the work of generating
  the Java interface files and the Java factory. You will still
  have to edit the generated files (for example, to fill in type
  information). But, it may save you a good deal of typing. You
  can find it here:
  `Jython/Java interface generator --
  http://www.rexx.com/~dkuhlman/JythonInterfaceGenerator-1.0a.tar.gz
  <http://www.rexx.com/~dkuhlman/JythonInterfaceGenerator-1.0a.tar.gz>`_.



Embedding Jython into Java
--------------------------


Why embedded Jython
~~~~~~~~~~~~~~~~~~~

There are several reasons and purposes for embedding the Jython
interpreter into your Java application:

- You want to offer your users the flexibility and power of
  customizing and extending your application. An embedded Jython
  interpreter enables them to run Jython scripts in your application
  and to communicate with it.

- You have existing Jython code, and you want to use that code in
  your Java application. Note that this is a capability that might
  have been handled by using the ``jythonc`` compiler to compile
  your Jython script into Java code, but ``jythonc`` is deprecated.
  For an example of this technique and information on how to do it,
  see section `Calling Jython from Java`_.


Embedding Jython into Java is simple
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Embedding the Jython interpreter can be as simple as this::

    // File: SimpleEmbedded.java
    import org.python.util.PythonInterpreter;
    import org.python.core.*;
    import java.io.*;

    public class SimpleEmbedded
    {
        public static void main(String[]args) throws PyException, IOException
        {
            BufferedReader terminal;
            PythonInterpreter interp;
            terminal = new BufferedReader(new InputStreamReader(System.in));
            System.out.println ("Hello");
            interp = new PythonInterpreter();
            interp.exec("import sys");
            interp.exec("print sys");
            interp.set("a", new PyInteger(42));
            interp.exec("print a");
            interp.exec("x = 2+2");
            PyObject x = interp.get("x");
            System.out.println("x: " + x);
            PyObject localvars = interp.getLocals();
            interp.set("localvars", localvars);
            String codeString = "";
            String prompt = ">> ";
            while (true)
            {
                System.out.print (prompt);
                try
                {
                    codeString = terminal.readLine();
                    if (codeString.compareTo("exit") == 0)
                    {
                        System.exit(0);
                        break;
                    }
                    interp.exec(codeString);
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            System.out.println("Goodbye");
        }
    }


Passing values into a Jython script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Notice the call ``interp.set("a", new PyInteger (42));`` in the
above example.

You can also retrieve the dictionary object representing the
namespace for the interpreter, then retrieve objects from that
dictionary. Example::

    PyDictionary namespace = interp.getLocals();
    PyObject obj = namespace.__getitem__("x");
    Integer x = obj.__tojava__(Integer.class);


Initializing the interpreter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can also create a Jython interpreter with an initial global
namespace::

    // File: TestInterp01.java

    import org.python.util.PythonInterpreter;
    import org.python.core.*;
    import java.io.*;

    public class TestInterp01
    {
        public static void main(String[]args) throws PyException, IOException
        {
            PythonInterpreter interp;
            PyString key;
            PyInteger value;
            System.out.println ("Hello");
            PyDictionary table = new PyDictionary();
            key = new PyString("aaa");
            value = new PyInteger(111);
            table.__setitem__(key, value);
            key = new PyString("bbb");
            value = new PyInteger(222);
            table.__setitem__(key, value);
            interp = new PythonInterpreter(table);
            interp.exec("print 'aaa:', aaa");
            interp.exec("print 'bbb:', bbb");
        }
    }

And, you can create an interpreter with an initial system state::

    // File: TestInterp02.java

    import org.python.util.PythonInterpreter;
    import org.python.core.*;
    import java.io.*;

    public class TestInterp02
    {
        public static void main(String[]args) throws PyException, IOException
        {
            PythonInterpreter interp;
            PyString key;
            PyInteger value;
            System.out.println ("Hello");
            PyDictionary table = new PyDictionary();
            key = new PyString("aaa");
            value = new PyInteger(111);
            table.__setitem__(key, value);
            key = new PyString("bbb");
            value = new PyInteger(222);
            table.__setitem__(key, value);
            PySystemState state = new PySystemState();
            interp = new PythonInterpreter(table, state);
            interp.exec("print 'aaa:', aaa");
            interp.exec("print 'bbb:', bbb");
        }
    }

This is of interest because the system state can be used to provide
a custom class loader::

    PyDictionary table = new PyDictionary();
    MyClassLoader classLoader = new MyClassLoader();
    PySystemState state = new PySystemState();
    state.setClassLoader(classLoader);
    PythonInterpreter interp = new PythonInterpreter(table, state);

And here is a sample class loader. This one merely restricts the
classes that can be loaded to a small set::

    // RestrictedClassLoader.java

    import java.util.Vector;
    import java.util.Enumeration;
    import java.lang.ClassNotFoundException;
     
    class RestrictedClassLoader extends ClassLoader {
        Vector goodnames;
        public RestrictedClassLoader () {
            goodnames = new Vector();
            goodnames.add("Goodclass1");
            goodnames.add("Goodclass2");
            goodnames.add("Goodclass3");
            goodnames.add("Goodclass4");
        }
        
        public Class findClass(String name) throws ClassNotFoundException {
            Enumeration items = goodnames.elements();
            while (items.hasMoreElements())
            {
                String item = (String)items.nextElement();
                if (item.compareTo(name) == 0)
                {
                    return super.findClass(name);
                }
            }
            throw new ClassNotFoundException("class loading restricted. " +
                name + " not allowed.");
        }
    }



Retrieving values from a Jython script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Notice the call ``PyObject x = interp.get("x");`` in the
above example.

You can also retrieve the dictionary object representing the
namespace for the interpreter, then add and modify the names and
their values in that dictionary. Example::

    PyDictionary namespace = interp.getLocals();
    PyInteger value = new PyInteger(144);
    namespace.__setitem__("x", value);


There are also a few complexities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You will want to *selectively* expose capabilities from your Java
application to scripts run by/on the embedded Jython interpreter.

You will want to protect your application from malicious or
erroneous scripts.

Here are a few suggestions:

- Describe your possible classes of users (those who will write
  scripts) with respect to (1) trusted vs. untrusted and (2) error
  tolerant vs. non-tolerant.

- For users who are trusted and error tolerant, provide
  transparent objects from your application.

- For users who are trusted and not error tolerant, provide opaque
  objects, i.e. wrappers for real objects from your application.

- For users who are not trusted, implement a security policy, *or*
  do not expose a scripting interface at all.


Exposing transparent objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Java application objects and values can be passed through to
scripts executed or evaluated by the embedded interpreter.

Some mechanisms for passing objects:

- ``set`` and ``get`` -- Use these to set or retrieve values in
  the local namespace for the scripts that your embedded
  interpreter will run or has run.

- ``setLocals`` and ``getLocals`` -- Using these methods, you can
  pass or retrieve the entire namespace. If you are inserting
  values to be used (or shared) by scripts, you may want to
  retrieve and, possibly, copy the initial namespace. Remember
  that is a Jython dictionary, so modifying it without copying may
  affect other scripts running in the same interpreter.


Exposing opaque objects
~~~~~~~~~~~~~~~~~~~~~~~

This is similar to the strategy for transparent objects, except
that you must implement wrapper classes, then provide instances of
these classes instead of instances of transparent objects.


Type conversion
~~~~~~~~~~~~~~~

Mostly, Jython takes care of this for you.

However, at times it may help to know what conversions are
performed.

And, you can also perform explicit conversions.


Using a custom class loader
~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can control access to Java classes with a custom class loader.
Here is an example::

    xxxx




Deployment and Distribution
===========================

Suppose we would like to package our Jython application in a Java
jar file, then deploy our application by distributing that jar file
so that our users can run it. And, furthermore, suppose we would
like our users to be able to run our Jython application on machines
where Jython is *not* installed.

This section explains how to do that. This explanation is also at:
`Distributing Jython Scripts --
http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts
<http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts>`_.

So, this boils down to:

- Having your scripts (``*.py``) inside standalone jython.jar in the
  /lib directory

- Having all the classes (``*.class``) in the /org or /com directory

- Having all the jar files you need on the classpath (including
  standalone ``jython.jar``)

- Start java with the ``-jar`` option. For example::

      $ java -jar jython.jar {optional .py file}


Building jars - some samples
----------------------------

The following examples assume that you want to build and run your
Jython application from a jar file in a way that is '''not'''
dependent on files in your Jython installation. This will enable
your users to run your Jython application (packaged in a jar file)
without installing Jython. They will, of course, need Java
installed on their machines.

The following example scripts were developed on Linux (and the bash
shell), but with minor modifications, you should be able to do the
same thing in an MS DOS box on MS Windows. I use the zip/unzip
tools available from Info-Zip (http://www.info-zip.org/), but other
tools that support the zip format should also work.


Add Jython install stuff to our jar
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To build our jar, we first make a copy of jython.jar, then add the
contents of the ``Lib/`` directory to it::

    $ cd $JYTHON_HOME
    $ cp jython.jar jythonlib.jar
    $ zip -r jythonlib.jar Lib


Add modules and paths to the jar file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Then we copy this expanded jar file, and add modules that are
specific to our application. I'm also going to add a path to an
additional jar file to the manifest::

    $ cd $MY_APP_DIRECTORY
    $ cp $JYTHON_HOME/jythonlib.jar myapp.jar
    $ zip myapp.jar Lib/showobjs.py
    # Add path to additional jar file.
    $ jar ufm myapp.jar othermanifest.mf

Where, othermanifest.mf contains the following::

    Class-Path: ./otherjar.jar

Run the script/jar
~~~~~~~~~~~~~~~~~~

Now I have a self-contained jar file that I can run by executing the
following::

    $ java -jar myapp.jar testmyapp.py

The file ``testmyapp.py`` imports modules that I have added to
``myapp.jar`` and ``otherjar.jar``, then starts my application.


A more self-contained jar file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now suppose you want to package your "start-up" script in the (main)
jar itself. In order to do so, follow the above instructions plus:

- Rename (or copy) your start-up script to ``__run__.py``. Add it
  to the (main) jar file at the root. (On Linux/UNIX you could also
  do this by using the ``ln -s`` command to create a symbolic
  link.) For example, you might do something like this::

      $ zip myapp.jar __run__.py

- Add the path to your jar to your CLASSPATH environment variable.

Now you can run your application with the following::

    $ java org.python.util.jython -jar myapp.jar

Notice how, when we start the application, we specify the jython
class (``org.python.util.jython``) on the command line. That
starts the Jython interpreter, which looks for and runs our
``__run__.py`` script.


A summary
~~~~~~~~~

Create the basic jar::

    $ cd $JYTHON_HOME
    $ cp jython.jar jythonlib.jar
    $ zip -r jythonlib.jar Lib

Add other modules to the jar::

    $ cd $MY_APP_DIRECTORY
    $ cp $JYTHON_HOME/jythonlib.jar myapp.jar
    $ zip myapp.jar Lib/showobjs.py
    # Add path to additional jar file.
    $ jar ufm myapp.jar othermanifest.mf

For a more self-contained jar, add the {{{__run__.py}}} module::

    # Copy or rename your start-up script.
    $ cp mymainscript.py __run__.py
    # Add your start-up script (__run__.py) ot the jar.
    $ zip myapp.jar __run__.py
    # Add path to main jar to the CLASSPATH environment variable.
    $ export CLASSPATH=/path/to/my/app/myapp.jar:$CLASSPATH

On MS Windows, that last line, setting the ``CLASSPATH``
environment variable, would look something like this::

    set CLASSPATH=C:\path\to\my\app\myapp.jar;%CLASSPATH%

Or, again on MS Windows, use the Control Panel and the System
properties to set the CLASSPATH environment variable.


Run the application::

    $ java -jar myapp.jar mymainscript.py arg1 arg2

Or, if you have added your start-up script to the jar::

    $ java org.python.util.jython -jar myapp.jar arg1 arg2



Integrating, Embedding, and Extending -- A Summary
==================================================

Here is what we have learned to do:

- Import and use Java classes in Jython.

- Extend a Java class in Jython.

- Implement Java classes that are more "Jythonic" and that expose
  Jython features such as doc-strings, inherit and extend Jython
  classes (for example, PyList, PyDict, etc.).

- Call Jython code from Java.

- Embed a Jython interpreter in a Java application.

- Package and deploy a Jython application as a jar file.



Jython+Java -- Other Advanced Topics
====================================

Event handling
--------------

Events are easy in Jython.

Here is an example taken from "An Introduction to Jython"
(http://www.javalobby.org/articles/jython/)::

    from javax.swing import *

    def hello(event):
        print "Hello. I'm an event."

    def test():
        frame = JFrame("Hello Jython")
        button = JButton("Hello", actionPerformed = hello)
        frame.add(button)
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        frame.setSize(300, 300)
        frame.show()

    test()


XML
---

jaxp
~~~~

Note: Tested with jython-2.2a.

Example::

    """

    To run this example, set your CLASSPATH with something like the following:

        export CLASSPATH=\
        ${path-to-xerces}/xerces-2_8_0/xercesImpl.jar:\
        ${path-to-xerces}/xerces-2_8_0/xml-apis.jar


    """


    import sys
    import java.lang.Boolean
    from javax.xml.parsers import DocumentBuilderFactory


    def test(infilename):
        """Parse XML document and show attributes and names.
        """
        dbf = DocumentBuilderFactory.newInstance()
        t = java.lang.Boolean(1)
        dbf.setNamespaceAware(t)
        db = dbf.newDocumentBuilder();
        doc = db.parse(infilename)
        # print dir(doc)
        node = doc.getDocumentElement()
        print 'Attributes:'
        show_attrs(node)
        print 'Names:'
        show_names(node)


    def show_attrs(node):
        """Show the attributes and their values.
        """
        node = node.getFirstChild()
        while node:
            if node.getNodeType() == node.ELEMENT_NODE:
                print ' %s:' % (node.getTagName(), )
                attrs = node.getAttributes()
                count = attrs.getLength()
                for idx in range(count):
                    attr = attrs.item(idx)
                    print ' %s: %s' % (
                        attr.getNodeName(), attr.getNodeValue(), )
            node = node.getNextSibling()


    def show_names(node):
        """Show the value of the name element for each person element.
        """
        node = node.getFirstChild()
        while node:
            if (node.getNodeType() == node.ELEMENT_NODE and
                node.getTagName() == 'person'):
                    show_person_name(node)
            node = node.getNextSibling()


    def show_person_name(node):
        node = node.getFirstChild()
        while node:
            if (node.getNodeType() == node.ELEMENT_NODE and
                node.getTagName() == 'name'):
                    show_text('name: ', node)
            node = node.getNextSibling()


    def show_text(msg, node):
        """Show a message and the value of a text node.
        """
        node = node.getFirstChild()
        while node:
            if node.getNodeType() == node.TEXT_NODE:
                print ' %s %s' % (msg, node.getNodeValue(), )
            node = node.getNextSibling()


    def usage():
        print 'Usage: jython test_jaxp.py <infilename>'
        sys.exit(-1)


    def main():
        args = sys.argv[1:]
        if len(args) != 1:
            usage()
        test(args[0])


    if __name__ == '__main__':
        main()



Resources:

- `jaxp: JAXP Reference Implementation
  <https://jaxp.dev.java.net/>`_
  (https://jaxp.dev.java.net/).

- `Java API for XML Processing (JAXP)
  <http://java.sun.com/webservices/jaxp/index.jsp>`_
  (http://java.sun.com/webservices/jaxp/index.jsp).


Xerces
~~~~~~

Xerces is an implementation of XML parsers and a lot more. The JAXP
API is also implemented in Xerces2.

Obtain Xerces here: http://xerces.apache.org/xerces2-j/download.cgi.

Installation instructions are here: `Installation Instructions
<http://xerces.apache.org/xerces2-j/install.html>`_.

Set-up -- Set your CLASSPATH. After unpacking the Xerces
distribution, add the following jar files to your CLASSPATH:

- xercesImpl.jar

- xml-apis.jar

Here is an example that uses the Xerces DOM parser to parse an XML
document, then print out information about the top level nodes in the
document::

    from org.apache.xerces.parsers import DOMParser as dp

    def test():
        parser = dp()
        parser.parse('people.xml')
        doc = parser.getDocument()
        node = doc.getFirstChild()
        node = node.getFirstChild()
        while node:
            if node.getNodeType() == node.ELEMENT_NODE:
                print node.getTagName()
                attrs = node.getAttributes()
                count = attrs.getLength()
                for idx in range(count):
                    attr = attrs.item(idx)
                    print ' %s: %s' % (attr.getNodeName(), attr.getNodeValue(),)
            node = node.getNextSibling()

    if __name__ == '__main__':
        test()


Here is another example. This one also prints out the text values of
the ``name`` elements::

    """

    To run this example, set your CLASSPATH with something like the following:

        export CLASSPATH=\
        ${path-to-jython2.2a}/jython.jar:\
        ${path-to-xerces}/xerces-2_8_0/xercesImpl.jar:\
        ${path-to-xerces}/xerces-2_8_0/xml-apis.jar


    """


    import sys
    from org.apache.xerces.parsers import DOMParser as dp


    def test(infilename):
        """Parse XML document and show attributes and names.
        """
        parser = dp()
        parser.parse(infilename)
        doc = parser.getDocument()
        node = doc.getFirstChild()
        print 'Attributes:'
        show_attrs(node)
        print 'Names:'
        show_names(node)


    def show_attrs(node):
        """Show the attributes and their values.
        """
        node = node.getFirstChild()
        while node:
            if node.getNodeType() == node.ELEMENT_NODE:
                print ' %s:' % (node.getTagName(), )
                attrs = node.getAttributes()
                count = attrs.getLength()
                for idx in range(count):
                    attr = attrs.item(idx)
                    print ' %s: %s' % (
                        attr.getNodeName(), attr.getNodeValue(), )
            node = node.getNextSibling()


    def show_names(node):
        """Show the value of the name element for each person element.
        """
        node = node.getFirstChild()
        while node:
            if (node.getNodeType() == node.ELEMENT_NODE and
                node.getTagName() == 'person'):
                    show_person_name(node)
            node = node.getNextSibling()


    def show_person_name(node):
        node = node.getFirstChild()
        while node:
            if (node.getNodeType() == node.ELEMENT_NODE and
                node.getTagName() == 'name'):
                    show_text('name: ', node)
            node = node.getNextSibling()


    def show_text(msg, node):
        """Show a message and the value of a text node.
        """
        node = node.getFirstChild()
        while node:
            if node.getNodeType() == node.TEXT_NODE:
                print ' %s %s' % (msg, node.getNodeValue(), )
            node = node.getNextSibling()


    def usage():
        print 'Usage: jython test_xerces.py <infilename>'
        sys.exit(-1)


    def main():
        args = sys.argv[1:]
        if len(args) != 1:
            usage()
        test(args[0])


    if __name__ == '__main__':
        main()


Notes:

- Except for the parser set-up (in function ``test``), this example
  is almost the same as the JAXP example. For the most part, it
  uses the same API.

Resources:

- `Xerces Java Parser <http://xerces.apache.org/xerces2-j/>`_

- `Introduction to XML and XML With Java
  <http://totheriver.com/learn/xml/xmltutorial.html>`_


dom4j
~~~~~

Example::


    """

    To run this example, add the following to your CLASSPATH:

        ${path-to-dom4j}/dom4j-1.6.1.jar


    """


    import sys
    from org.dom4j.io import SAXReader

    def show_indent(level):
        return ' ' * level

    def show_node(node, level):
        """Display one node in the DOM tree.
        """
        if node.getNodeType() == node.ELEMENT_NODE:
            name = node.getName()
            print '%sNode: %s' % (show_indent(level), name, )
            attrs = node.attributes()
            for attr in attrs:
                aName = attr.getQualifiedName()
                aValue = attr.getValue()
                print ' %sAttr -- %s: %s' % (show_indent(level), aName, aValue,)
        if node.getName() == 'interest':
            val = node.getText()
            print '%sinterest: "%s"' % (show_indent(level+1), val, )
        elif node.getName() == 'name':
            val = node.getText()
            print '%sname : "%s"' % (show_indent(level+1), val, )
        #
        # Note that there are *no* TEXT_NODE's.
        # dom4j does not seem to produce any.
        #
        if node.getNodeType() == node.TEXT_NODE:
            print '**** text node'


    def show_tree(node, level):
        show_node(node, level)
        level1 = level + 1
        children = node.elements()
        for child in children:
            show_tree(child, level1)

    def test():
        print 'Version: %s' % (sys.version, )
        reader = SAXReader()
        doc = reader.read('file:///home/dkuhlman/a1/Python/Jython/Test/people.xml')
        root = doc.getRootElement()
        show_tree(root, 0)

    def main():
        test()

    if __name__ == '__main__':
        #import pdb; pdb.set_trace()
        main()


Resources:

- http://www.dom4j.org/

- http://www.dom4j.org/dom4j-1.4/apidocs/index.html



Database access
---------------

JDBC
~~~~

JDBC is Java classes. It is, therefore, usable from Jython.

You will need JDBC driver/adapters for your database.

But, JDBC is not very Pythonic.


zxJDBC
~~~~~~

zxJDBC *is* Pythonic. zxJDBC implements the Python DB API on top
of JDBC. For more on the Python DB API, see
`SIG on Tabular Databases in Python
<http://python.org/sigs/db-sig/>`_ and
`Python Database API Specification v2.0
<http://python.org/peps/pep-0249.html>`_.


If zxJDBC is not already in your installed version of Jython, then
you can:

1. Downloading the source from
   http://sourceforge.net/projects/zxjdbc.

2. Creating a directory (e.g. ``zxJDBC``), then un-rolling it.

3. Add ``zxJDBC/lib/zxJDBC.jar`` to your ``CLASSPATH``

You can get documentation on zxJDBC by:

1. Downloading the source from
   http://sourceforge.net/projects/zxjdbc.

2. Creating a directory (e.g. ``zxJDBC``), then un-rolling it.

3. Pointing your browser at ``zxJDBC/doc/index.html``.

Example -- The following example opens a connection to a
PostgreSQL database, then prints out the rows in a table in that
database. In order to make this example work, I put the following
jar files on my ``CLASSPATH``:

- ``zxJDBC.jar`` -- Not needed for Jython 2.2, and possibly not
  needed for the version of Jython 2.1 on your machine. JDBC
  support has been folded into Jython 2.1 and Jython 2.2a.

- ``postgresql-8.1-407.jdbc3.jar`` -- You will need a suitable
  driver for your database and version.

Here is the example implementation::

    """

    For this test, add the JDBC driver to your CLASSPATH. For example,
    in my case I added:

        postgresql-8.1-407.jdbc3.jar

    """

    from com.ziclix.python.sql import zxJDBC

    def test():
        d, u, p, v = (
            "jdbc:postgresql://thrush:5432/test", # ... host, port, database
            "postgres", # user name
            "mypassword", # pass word
            "org.postgresql.Driver", # driver
            )
        db = zxJDBC.connect(d, u, p, v, CHARSET='iso_1')
        cur = db.cursor()
        cur.execute('select * from plant_db')
        rows = cur.fetchall()
        s1 = '%s %s %s' % (
            'Name'.ljust(12),
            'Description'.ljust(24),
            'Rating'.ljust(10),
            )
        print s1
        s1 = '%s %s %s' % (
            '===='.ljust(12),
            '==========='.ljust(24),
            '======'.ljust(10),
            )
        print s1
        for row in rows:
            rating = str(row[2])
            print '%s %s %s' % (
                row[0].ljust(12), row[1].ljust(24), rating.ljust(10), )
        cur.close()
        db.close()

    if __name__ == '__main__':
        test()


Which, when connected to my trivial, little database, prints out
the following::

    Name Description Rating
    ==== =========== ======
    tomato red and tasty 8
    peach sweet and succulent 8
    tangerine sweet but tart 7


Resources:

- Python Tabular Databases SIG: Status
  <http://www.python.org/community/sigs/current/db-sig/status/>`_
  (http://www.python.org/community/sigs/current/db-sig/status/).

- The Python `Database Topic Guide
  <http://www.python.org/doc/topics/database/>`_
  (http://www.python.org/doc/topics/database/).

- More information on zxJDBC:
  http://sourceforge.net/projects/zxjdbc

- The JDBC driver for PostgreSQL: http://jdbc.postgresql.org/

- The JDBC driver for MySQL:
  http://www.mysql.com/products/connector/j/


Additional Exercises
====================

[To be added.]


References and Sources
======================

Introductory articles:

- `An Introduction to Jython`_: An introductory article on Jython

- `alt.lang.jre: Get to know Jython`_: An introduction to Jython
  that includes a summary of Jython features.

- `Use Jython to Exercise Java APIs Without Compiling`_: Another
  introduction with an emphasis on the use of Java classes.

- `Charming Jython`_: Yet another introductory article.

- `Scripting Languages For Java`_: A comparison of scripting
  languages for Java.

.. _`An Introduction to Jython`:
    http://www.javalobby.org/articles/jython/

.. _`alt.lang.jre: Get to know Jython`:
    http://www-128.ibm.com/developerworks/library/j-alj07064/index.html

.. _`Use Jython to Exercise Java APIs Without Compiling`:
    http://www.devx.com/Java/Article/27571/1954?pf=true

.. _`Charming Jython`:
    http://www-128.ibm.com/developerworks/java/library/j-jython.html

.. _`Scripting Languages For Java`:
    http://www.ociweb.com/jnb/archive/jnbMar2001.html

Thanks to David Goodger for the following list or references. His
"Code Like a Pythonista: Idiomatic Python"
(http://python.net/~goodger/projects/pycon/2007/idiomatic/) is worth
a careful reading:

- "Python Objects", Fredrik Lundh,
  http://www.effbot.org/zone/python-objects.htm

- "How to think like a Pythonista", Mark Hammond,
  http://python.net/crew/mwh/hacks/objectthink.html

- "Python main() functions", Guido van Rossum,
  http://www.artima.com/weblogs/viewpost.jsp?thread=4829

- "Python Idioms and Efficiency",
  http://jaynes.colorado.edu/PythonIdioms.html

- "Python track: python idioms",
  http://www.cs.caltech.edu/courses/cs11/material/python/misc/python_idioms.html

- "Be Pythonic", Shalabh Chaturvedi,
  http://shalabh.infogami.com/Be_Pythonic2

- "Python Is Not Java", Phillip J. Eby,
  http://dirtsimple.org/2004/12/python-is-not-java.html

- "What is Pythonic?", Martijn Faassen,
  http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0

- "Sorting Mini-HOWTO", Andrew Dalke,
  http://wiki.python.org/moin/HowTo/Sorting

- "Python Idioms", http://www.gungfu.de/facts/wiki/Main/PythonIdioms

- "Python FAQs", http://www.python.org/doc/faq/







.. Configuration for Emacs
..
   Local Variables:
   mode: indented-text
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 68
   End:
Wizja krople może pomoże dokonać zobacz połysk. W ten sposób, można Przystanek rozdrażnienie i sucha skóra również Podczas korzystania Twoja wizja wiele w pracy, w tym w Komputer osobisty Terminal, utrzymać oczy spadki wygodny. Zachowaj Pakiet poręczny w bliskim sąsiedztwie Twoja biurko, i miejsce te spadki ze swoimi oko każdy liczba czas. downy ([[http://bookmarks-hit.com/story.php?title=dobry-stomatolodzy-plock-w-przypadku-jestes-nieustannie-uzyskac-tradzik-tylko-na-|bookmarks-hit.com]]) tojoin zimmer ([[http://www.e-fotografija.com/forum2/profile.php?mode=viewprofile&u=125754|http://www.e-fotografija.com/forum2/profile.php?mode=viewprofile&u=125754]]) redeem s's ([[http://www.koicaecuador.com/koicaecuador/xe/?document_srl=645674|http://www.koicaecuador.com/koicaecuador/xe/?document_srl=645674]]) istotne rzecz zapobiec starzeje i podbicie długość życia jest nie dym papierosowy . Palenie papierosów szkody ciało i przyspiesza starzeje. Palenie papierosów jest najskuteczniejszym sposobem pojawiać więcej w wieku i skrócić Twoja długość życia równocześnie. To przyczyny Stan, przedziały wiekowe skóra, a także ogólnie jeden z główna uniknąć mordercy znane facet. reducing ([[http://www.nleq.info/bookmarks.php/virgimcnicoll|www.nleq.info]]) Nie bać do grać z nim jeśli chodzi o mając doskonały wina. Pewna, wszyscy mamy ulubionych wstać-by, ale to nie sugerują jedno inne nie może być loved także Jeśli czerwony może być twój przejdź do wino, zbadać szansa albo może być bold i sprawdzić coś już w żaden sposób słyszał nawet! thunderball - [[http://cai.mingdao.edu.tw/2008/2008x7/userinfo.php?uid=69379|http://cai.mingdao.edu.tw/2008/2008x7/userinfo.php?uid=69379]] - hopper separatist [[[http://mysrm.srmuniv.ac.in/bio_ethics/node/33384|http://mysrm.srmuniv.ac.in]]] sloan cyst - [[http://girlsgonegross.com/phpBB2/profile.php?mode=viewprofile&u=508907|girlsgonegross.com]] - Dobry wskazówkę jeśli zainteresowany dowiedzieć się więcej o tym, wino jest iść do tyle, wino degustacje jak można. Wino są świetne degustacje ponieważ pozwala wypróbować Wszystkie rodzaje wina która pomaga jesteś ocenić, które lubisz i cokolwiek nie lubię. insecurities ([[http://megalith.fr.nf/forum/profile.php?id=165473|fr.nf]]) brookfield goodies ([[http://www.zyngaplayerforums.com/member.php?u=4559041-BJgq|www.zyngaplayerforums.com]]) incoherently barracks - [[http://studyandmigrate.com/modules.php?name=Your_Account&op=userinfo&username=BNorwood|studyandmigrate.com]], Ćwiczenie jest coś należy sposób przez minimum 4 dni przez kilka dni . przybyć centrum odnowy biologicznej tak często jak możesz i działa na z urządzeni bieżnia mieć h. To pomoże do spłukiwania Ciało wewnętrznie pomóc zredukować toksyny i wolne rodniki że wywołują starzenie. dobisch, [[http://kenyacoast.net/profile-13061/info/|kenyacoast.net]], testimonial lucignolo ([[http://www.mojarekomendacja.pl/profile.php?mode=viewprofile&u=321344|mojarekomendacja.pl]]) appeal snowball ([[http://geumsaem.org/xe/?document_srl=1345444|geumsaem.org]]) Możesz ewentualnie nie używania czasie rzeczywistym mechaniczny, ale to nie sugerować nie możesz sobie wyglądać młodziej. Teraz już przeczytać to artykuł, mam trochę fantastycznych wspaniałych pomysłów, jak słaby proces starzenia i sprawdzić odmłodzony niż stało się. Osoby spełnić będziesz czuję, że jesteś sensowne poza od wielu lat. callaghan - [[http://seoway4u.com/user.php?login=th46|http://seoway4u.com/user.php?login=th46]], gypsy disbelieve ([[http://www.ecowater.re.kr/xe/?document_srl=4493099|www.ecowater.re.kr]]) pelle illustration ([[http://www.heemang21.net/?document_srl=860059|http://www.heemang21.net/?document_srl=860059]]) Squirt mgła nad twoja twarz skoro masz twój makijaż wykorzystywane. To będzie skonfigurować na makijaż i utrzymania to gdzie być powinno przez dłuższy czas. To może być doskonały technika używać jeśli masz rozległe dni po przed lubisz jeśli jest, Twój wielki dzień lub że mam wieczór zwłaszcza po pracy ułożone. slashing ([[http://ecolecoree.korean.net/ecbbs/?document_srl=221538|ecolecoree.korean.net]]) ulan configuration [[[http://bbs.kpopwave.joins.com/?document_srl=4640098|bbs.kpopwave.joins.com]]] calendar provocations, [[http://www.freebooks4islam.com/bb/profile.php?mode=viewprofile&u=774955|http://www.freebooks4islam.com/]], Nie zapomnieć do grać z nim w stosunku do cieszy doskonały vino. Oczywiście, każdy ma ulubionych wstać-by, ale to nie sugerować coś odrębne nie może być cieszył w tym samym czasie. Jeśli czerwonawe będzie twoim przejdź do wino, wymeldowanie szansa lub być naprawdę śmiały i sprawdzić coś już w żaden sposób przeczytaj o! cautioned ([[http://corvalgroup.com/news/492090|corvalgroup.com]]) stanley's celine ([[http://www.rpgresearch.org/forums/profile.php?mode=viewprofile&u=238061|www.rpgresearch.org]]) solo depart ([[http://malteseclub.ru/phpBB2/profile.php?mode=viewprofile&u=385717|http://malteseclub.ru/]]) Zawsze wiedzieć, które wino są w sezonie. Przez każdym sezonie, rozne wino może Uznanie zależy wakacje przerwa lub rok. Stacja dokująca wina są wielki pokaz, a oni mają tendencję do Wzrost wzrost w cena w dni prowadzi do Boże Narodzenie . Kiedy wiesz, wina przez ich warunki, można kupić - Okres i pomóc uratować. tarumi - [[http://www.thepigsite.com/forums/member.php?u=309379|http://www.thepigsite.com/forums/member.php?u=309379]], gïnna stefano ([[http://www.gusto.com.tw/userinfo.php?uid=62406|http://www.gusto.com.tw]]) sal's braxton ([[http://www.hisho53.com/xoops/html/userinfo.php?uid=6504|http://www.hisho53.com/]]) Przy zakupie wino, poszukiwania pojemniki można oczekiwać zużywają. Nie pozwolenie Ekspert lub nawet sprzedawcy wpływ. Nie ma absolutnie żadnego wykorzystania w Pobranie drogie pojemnik mieć okazję do zużywają może nie cieszyć się tym pewien wino. redevelopment ([[http://www.brugsebuurten.be/wiek/forum/profile.php?mode=viewprofile&u=36745|www.brugsebuurten.be]]) collier larry ([[http://kenyacoast.net/profile-13061/info/|kenyacoast.net]]) richmond blackmailed ([[http://www.aparus.ru/userinfo.php?uid=189752|http://www.aparus.ru]]) Pamiętaj, że nadmierne ekspozycji na słońce nie tylko zły skóra, jest również szkodliwe dla włosy. powodu ekspozycji na słońce czupryna może stać suche, kruche, narażone i odbarwione. Ekspozycja na słońce może RIP białka Połączenia w twoim czupryna i zrobić własne włosy całkowicie słabszy. Więc, jeśli będzie być ostrzał czasu i wysiłku w słońcu, upewnij się, założyć nakryciem głowy. gesture ([[http://www.rpgresearch.org/forums/profile.php?mode=viewprofile&u=238061|rpgresearch.org]]) rippin masson ([[http://www.buddhatu-hk.org/userinfo.php?uid=185627|www.buddhatu-hk.org]]) comfortably chorizo ([[http://www.8xalpha.com/profile_info.php?ID=52635|www.8xalpha.com]]) ogloszenia Weź udział w profesjonaliści ale zazwyczaj nie kierowania ich też naprawdę bardzo poważnie. Najskuteczniejszym wino specjaliści chcą Przyznaję ich błędy. Dodatkowo, rozumiem, że ludzi różne podniebienia. Niezbędne jest mieć zaufanie osobiste Preferencje, również. baii ([[http://www.tatuki.jp/userinfo.php?uid=66053|www.tatuki.jp]]) marlln supermodel - [[http://www.rpgresearch.org/forums/profile.php?mode=viewprofile&u=238061|www.rpgresearch.org]], inciting calculated ([[http://www.doublefinish.com/vbul/member.php?u=6235-HWhitmore|doublefinish.com]]) Praca na swoim osobistego obrazu podczas gdy w starzenie jest krytyczna. Osobiste wizerunek jest bardzo ważne jak Europejski etniczną zazwyczaj pozycja znacznymi ilościami skupić się na młodsi ludzie i należy - osobisty szacunek podczas starzenie. Nawet media i popularne tradycja jest pasjonatem młodszych lat, że nie zawsze oznacza może nie problem!

Wizja krople może pomoże dokonać zobacz połysk. W ten sposób, można Przystanek rozdrażnienie i sucha skóra również Podczas korzystania Twoja wizja wiele w pracy, w tym w Komputer osobisty Terminal, utrzymać oczy spadki wygodny. Zachowaj Pakiet poręczny w bliskim sąsiedztwie Twoja biurko, i miejsce te spadki ze swoimi oko każdy liczba czas. downy (bookmarks-hit.com) tojoin zimmer (http://www.e-fotografija.com/forum2/profile.php?mode=viewprofile&u=125754) redeem s's (http://www.koicaecuador.com/koicaecuador/xe/?document_srl=645674) istotne rzecz zapobiec starzeje i podbicie długość życia jest nie dym papierosowy . Palenie papierosów szkody ciało i przyspiesza starzeje. Palenie papierosów jest najskuteczniejszym sposobem pojawiać więcej w wieku i skrócić Twoja długość życia równocześnie. To przyczyny Stan, przedziały wiekowe skóra, a także ogólnie jeden z główna uniknąć mordercy znane facet. reducing (www.nleq.info) Nie bać do grać z nim jeśli chodzi o mając doskonały wina. Pewna, wszyscy mamy ulubionych wstać-by, ale to nie sugerują jedno inne nie może być loved także Jeśli czerwony może być twój przejdź do wino, zbadać szansa albo może być bold i sprawdzić coś już w żaden sposób słyszał nawet! thunderball - http://cai.mingdao.edu.tw/2008/2008x7/userinfo.php?uid=69379 - hopper separatist http://mysrm.srmuniv.ac.in] sloan cyst - girlsgonegross.com - Dobry wskazówkę jeśli zainteresowany dowiedzieć się więcej o tym, wino jest iść do tyle, wino degustacje jak można. Wino są świetne degustacje ponieważ pozwala wypróbować Wszystkie rodzaje wina która pomaga jesteś ocenić, które lubisz i cokolwiek nie lubię. insecurities (fr.nf) brookfield goodies (www.zyngaplayerforums.com) incoherently barracks - studyandmigrate.com, Ćwiczenie jest coś należy sposób przez minimum 4 dni przez kilka dni . przybyć centrum odnowy biologicznej tak często jak możesz i działa na z urządzeni bieżnia mieć h. To pomoże do spłukiwania Ciało wewnętrznie pomóc zredukować toksyny i wolne rodniki że wywołują starzenie. dobisch, kenyacoast.net, testimonial lucignolo (mojarekomendacja.pl) appeal snowball (geumsaem.org) Możesz ewentualnie nie używania czasie rzeczywistym mechaniczny, ale to nie sugerować nie możesz sobie wyglądać młodziej. Teraz już przeczytać to artykuł, mam trochę fantastycznych wspaniałych pomysłów, jak słaby proces starzenia i sprawdzić odmłodzony niż stało się. Osoby spełnić będziesz czuję, że jesteś sensowne poza od wielu lat. callaghan - http://seoway4u.com/user.php?login=th46, gypsy disbelieve (www.ecowater.re.kr) pelle illustration (http://www.heemang21.net/?document_srl=860059) Squirt mgła nad twoja twarz skoro masz twój makijaż wykorzystywane. To będzie skonfigurować na makijaż i utrzymania to gdzie być powinno przez dłuższy czas. To może być doskonały technika używać jeśli masz rozległe dni po przed lubisz jeśli jest, Twój wielki dzień lub że mam wieczór zwłaszcza po pracy ułożone. slashing (ecolecoree.korean.net) ulan configuration bbs.kpopwave.joins.com] calendar provocations, http://www.freebooks4islam.com/, Nie zapomnieć do grać z nim w stosunku do cieszy doskonały vino. Oczywiście, każdy ma ulubionych wstać-by, ale to nie sugerować coś odrębne nie może być cieszył w tym samym czasie. Jeśli czerwonawe będzie twoim przejdź do wino, wymeldowanie szansa lub być naprawdę śmiały i sprawdzić coś już w żaden sposób przeczytaj o! cautioned (corvalgroup.com) stanley's celine (www.rpgresearch.org) solo depart (http://malteseclub.ru/) Zawsze wiedzieć, które wino są w sezonie. Przez każdym sezonie, rozne wino może Uznanie zależy wakacje przerwa lub rok. Stacja dokująca wina są wielki pokaz, a oni mają tendencję do Wzrost wzrost w cena w dni prowadzi do Boże Narodzenie . Kiedy wiesz, wina przez ich warunki, można kupić - Okres i pomóc uratować. tarumi - http://www.thepigsite.com/forums/member.php?u=309379, gïnna stefano (http://www.gusto.com.tw) sal's braxton (http://www.hisho53.com/) Przy zakupie wino, poszukiwania pojemniki można oczekiwać zużywają. Nie pozwolenie Ekspert lub nawet sprzedawcy wpływ. Nie ma absolutnie żadnego wykorzystania w Pobranie drogie pojemnik mieć okazję do zużywają może nie cieszyć się tym pewien wino. redevelopment (www.brugsebuurten.be) collier larry (kenyacoast.net) richmond blackmailed (http://www.aparus.ru) Pamiętaj, że nadmierne ekspozycji na słońce nie tylko zły skóra, jest również szkodliwe dla włosy. powodu ekspozycji na słońce czupryna może stać suche, kruche, narażone i odbarwione. Ekspozycja na słońce może RIP białka Połączenia w twoim czupryna i zrobić własne włosy całkowicie słabszy. Więc, jeśli będzie być ostrzał czasu i wysiłku w słońcu, upewnij się, założyć nakryciem głowy. gesture (rpgresearch.org) rippin masson (www.buddhatu-hk.org) comfortably chorizo (www.8xalpha.com) ogloszenia Weź udział w profesjonaliści ale zazwyczaj nie kierowania ich też naprawdę bardzo poważnie. Najskuteczniejszym wino specjaliści chcą Przyznaję ich błędy. Dodatkowo, rozumiem, że ludzi różne podniebienia. Niezbędne jest mieć zaufanie osobiste Preferencje, również. baii (www.tatuki.jp) marlln supermodel - www.rpgresearch.org, inciting calculated (doublefinish.com) Praca na swoim osobistego obrazu podczas gdy w starzenie jest krytyczna. Osobiste wizerunek jest bardzo ważne jak Europejski etniczną zazwyczaj pozycja znacznymi ilościami skupić się na młodsi ludzie i należy - osobisty szacunek podczas starzenie. Nawet media i popularne tradycja jest pasjonatem młodszych lat, że nie zawsze oznacza może nie problem!

LearningJython (last edited 2018-03-07 21:17:20 by JeffAllen)