Szymon Wróblewski avatar Szymon Wróblewski committed a4e63e7

updated setup script, changed documentation and test directory structure

Comments (0)

Files changed (22)

+syntax: glob
+.*
+*.pyc
+dist
+build
+MANIFEST
-include *.txt
-prune doc
+include *.txt *.rst
+prune .*
 SPHINXOPTS    =
 SPHINXBUILD   = sphinx-build
 PAPER         =
-BUILDDIR      = build
+BUILDDIR      = ../build/sphinx
 
 # Internal variables.
 PAPEROPT_a4     = -D latex_paper_size=a4
 PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
 # the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
 
Add a comment to this file

doc/_static/pygnetic.png

Added
New image

doc/api/index.rst

+:mod:`pygnetic` Package
+=======================
+
+.. automodule:: pygnetic
+
+   .. autofunction:: init([events[, event_val[, logging_lvl[, n_module[, s_module]]]]])
+   
+   .. autofunction:: register(name[, field_names[, **kwargs]])
+   
+      .. note:: It uses :data:`.message.message_factory`
+      
+   .. autoclass:: Client
+   
+   .. autoclass:: Server
+   
+   .. class :: Handler
+   
+      :class:`handler.Handler` binding.
+   
+   
+:mod:`client` Module
+--------------------
+
+.. automodule:: pygnetic.client
+    
+   .. autoclass:: Client([conn_limit, [*args, **kwargs]])
+    
+      Example::
+      
+         client = pygnetic.client.Client()
+         connection = client.connect("localhost", 10000)
+         while True:
+            client.update()
+            
+      .. data:: message_factory
+         
+         Default :class:`~.message.MessageFactory` object used for new
+         connections. (default: :data:`.message.message_factory`)
+      
+      .. automethod:: connect(host, port[, message_factory[, **kwargs]])
+      
+      .. automethod:: update(self[, timeout])
+
+
+:mod:`connection` Module
+------------------------
+
+.. automodule:: pygnetic.connection
+    
+   .. autoclass:: Connection(parent, conn_obj, message_factory)
+      
+      Example::
+      
+         # assuming chat_msg message is already defined
+         connection.net_chat_msg('Tom', 'Test message')
+         # alternative
+         connection.send(chat_msg, 'Tom', 'Test message')
+         # or
+         connection.send('chat_msg', 'Tom', 'Test message')
+      
+      .. attribute:: parent
+      
+         :func:`Proxy <weakref.proxy>` to Client / Server instance
+         
+      .. attribute:: address
+      
+         Connection address
+         
+      .. attribute:: connected
+      
+         True if connected
+         
+      .. attribute:: data_sent
+      
+         Amount of data sent
+         
+      .. attribute:: data_received
+      
+         Amount of data received
+         
+      .. attribute:: messages_sent
+      
+         Amount of messages sent
+         
+      .. attribute:: messages_received
+      
+         Amount of messages received
+         
+      .. automethod:: add_handler(handler)
+      
+      .. automethod:: disconnect([*args])
+      
+      .. method:: net_message_name([\*args, \*\*kwargs])
+
+         Send ``message_name`` messagge to remote host.
+         
+         :param args: parameters used to initialize message object
+         :param kwargs: keyword parameters used to initialize message object
+         
+         It uses :meth:`__getattr__ <object.__getattr__>` mechanism to add
+         :meth:`net_message_name` :func:`partial <functools.partial>` method
+         to class and call it. Any subsequent call is realized by new method.
+      
+      .. automethod:: send(message[, *args, **kwargs])
+         
+
+
+:mod:`event` Module
+-------------------
+
+.. automodule:: pygnetic.event
+   
+   .. data:: NETWORK
+
+   .. data:: NET_DISCONNECTED
+   
+   .. data:: NET_CONNECTED
+   
+   .. data:: NET_ACCEPTED
+   
+   .. data:: NET_RECEIVED
+   
+   Event attributes:
+   
+      Connected event
+         | ``type`` = :const:`NETWORK`
+         | ``net_type`` = :const:`NET_CONNECTED`
+         | ``connection`` -- connection
+      
+      Disconnected event
+         | ``type`` = :const:`NETWORK`
+         | ``net_type`` = :const:`NET_DISCONNECTED`
+         | ``connection`` -- connection
+      
+      Accepted event
+         | ``type`` = :const:`NETWORK`
+         | ``net_type`` = :const:`NET_ACCEPTED`
+         | ``connection`` -- connection
+      
+      Received event
+         | ``type`` = :const:`NETWORK`
+         | ``net_type`` = :const:`NET_RECEIVED`
+         | ``connection`` -- connection
+         | ``message`` -- received message
+         | ``msg_type`` -- message type
+   
+   Example::
+
+      for e in pygame.event.get():
+          if e.type == event.NETWORK:
+              if e.net_type == event.NET_CONNECTED:
+                  print 'connected'
+              elif e.net_type == event.NET_DISCONNECTED:
+                  print 'disconnected'
+              elif e.net_type == event.NET_RECEIVED:
+                  # assuming chat_msg message is already defined
+                  if e.msg_type == chat_msg:
+                      print '%s: %s' % (e.message.player, e.message.msg)
+                  else:
+                      print 'received:', e.message
+   
+   .. note::
+      
+      To use events you need to enable them with :func:`.init`
+   
+   .. warning::
+   
+      If you plan to change value of :const:`NETWORK` with
+      :func:`.init`, then use:: 
+         
+         import pygnetic.event as event
+         # rather than
+         # from pygnetic.event import NETWORK
+
+
+:mod:`handler` Module
+---------------------
+
+.. automodule:: pygnetic.handler
+
+   .. autoclass:: Handler
+   
+      .. attribute:: connection
+      
+         :func:`Proxy <weakref.proxy>` to :class:`~.connection.Connection`
+         derived class instance
+         
+      .. attribute:: server
+      
+         :func:`Proxy <weakref.proxy>` to :class:`~.server.Server`
+         derived class instance   
+      
+      .. method:: net_message_name(message[, **kwargs])
+      
+         Called when ``message_name`` message is received
+         
+         :param message: received message
+         :param kwargs:
+            additional keyword arguments from :term:`network adapter`
+      
+      .. automethod:: on_connect
+      
+      .. automethod:: on_disconnect
+      
+      .. automethod:: on_recive(message[, **kwargs])
+
+
+:mod:`message` Module
+---------------------
+
+.. automodule:: pygnetic.message
+
+   .. data:: message_factory
+      
+      Default instance of :class:`MessageFactory` used by other modules.
+   
+   .. autoclass:: MessageFactory([s_adapter])
+   
+      Example::
+      
+         chat_msg = MessageFactory.register('chat_msg', ('player', 'msg'))
+         data = MessageFactory.pack(chat_msg('Tom', 'Test message'))
+         message = MessageFactory.unpack(data)
+         player = message.player
+         msg = message.msg
+         
+      .. note::
+      
+         You can create more instances of :class:`MessageFactory` when you want
+         to separate messages for different connections in
+         :class:`~.client.Client`.
+      
+      .. automethod:: get_by_name
+      
+      .. automethod:: get_by_type
+      
+      .. automethod:: get_hash
+      
+      .. automethod:: get_params
+      
+      .. automethod:: get_type_id
+      
+      .. automethod:: pack
+      
+      .. automethod:: register(name[, field_names[, **kwargs]])
+      
+      .. automethod:: reset_context
+      
+      .. automethod:: set_frozen
+      
+      .. automethod:: unpack
+      
+      .. automethod:: unpack_all
+
+
+:mod:`server` Module
+--------------------
+
+.. automodule:: pygnetic.server
+    
+   .. autoclass:: Server([host[, port[, conn_limit[, *args, **kwargs]]]])
+      
+      .. attribute:: address
+         
+         Server address.
+         
+      .. automethod:: connections([exclude])
+      
+      .. automethod:: handlers([exclude])
+      
+      .. automethod:: update([timeout])
+
+
+Small FAQ
+=========
+
+**Why I have to register message? Can't I just use dictionary to send it?**
+   :meth:`~.message.MessageFactory.register` creates a compact
+   data structure - :func:`namedtuple <collections.namedtuple>`, which contains
+   only essential data, reducing overall amount of data to send. Take a look at
+   example below and compare sizes of packed dictionary and structure created
+   by :class:`~.message.MessageFactory`.
+
+      >>> import msgpack
+      >>> m1 = msgpack.packb({'action':'chat_msg', 'player':'Tom', 'msg':'Test message'})
+      >>> m1, len(m1)
+      ('\x83\xa6action\xa8chat_msg\xa6player\xa3Tom\xa3msg\xacTest message', 45)
+      >>> import pygnetic as net
+      >>> net.init()
+      17:11:40 INFO     Using enet_adapter
+      17:11:40 INFO     Using msgpack_adapter
+      True
+      >>> chat_msg = net.register('chat_msg', ('player', 'msg'))
+      >>> m2 = net.message.message_factory.pack(chat_msg('Tom', 'Test message'))
+      >>> m2, len(m2)
+      ('\x93\x02\xa3Tom\xacTest message', 19)
+
+   The only drawback of this method is the need to register the same messages
+   in the same order in client and server.
+
+**Why order of registration messages is important?**
+   As You may noticed in previous example, there is no string with type of
+   message in packed data. That's because type is encoded as integer,
+   depending on order of registration.
+
+
+Glossary
+========
+
+.. glossary::
+   :sorted:
+
+   network adapter
+      class providing unified interface for different network libraries
+      
+   serialization adapter
+      class providing unified interface for different serialization libraries
+# -*- coding: utf-8 -*-
+#
+# pygnetic documentation build configuration file, created by
+# sphinx-quickstart on Sun Jun 17 20:09:12 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('..'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
+extensions = ['sphinx.ext.autodoc',
+              'sphinx.ext.viewcode',
+              'sphinx.ext.intersphinx',
+              ]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'pygnetic'
+copyright = u'2012, Szymon Wróblewski'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+import pygnetic
+import distutils.version
+v = distutils.version.StrictVersion(pygnetic.__version__)
+# The short X.Y version.
+version = '.'.join(map(str, v.version[:2]))
+# The full version, including alpha/beta/rc tags.
+release = str(v)
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+intersphinx_mapping = {
+    'python': ('http://python.readthedocs.org/en/latest/', None),
+}
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = '_static/pygnetic.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'pygneticdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'pygnetic.tex', u'Pygame network Documentation',
+   u'Szymon Wróblewski', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'pygnetic', u'pygnetic Documentation',
+     [u'Szymon Wróblewski'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'pygnetic', u'pygnetic Documentation',
+   u'Szymon Wróblewski', 'pygnetic', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'pygnetic'
+epub_author = u'Szymon Wróblewski'
+epub_publisher = u'Szymon Wróblewski'
+epub_copyright = u'2012, Szymon Wróblewski'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+Examples
+========
+
+.. literalinclude:: ../test_server.py
+
+.. literalinclude:: ../test_client_2.py
+pygnetic --- Easy networking in Pygame
+======================================
+
+**pygnetic** is a library designed to help in the development of
+network games and applications in `Pygame <http://www.pygame.org>`_.
+
+
+Features
+--------
+
+* Two approaches to handle network events
+   * generating events in pygame queue
+   * using handler classes
+* Efficient packaging of data through the message system
+* Support for multiple network and serialization libraries
+
+
+Contents
+--------
+
+.. toctree::
+   :maxdepth: 2
+   :glob:
+
+   api/index
+   examples
+   license
+
+
+Installation
+------------
+
+**pygnetic** can be installed with
+`windows installer <http://pypi.python.org/pypi/pygnetic/#downloads>`_
+or with `pip <http://www.pip-installer.org>`_::
+
+   pip install pygnetic
+
+
+Optional requirements
+---------------------
+
+* `Message Pack <http://msgpack.org/>`_ (recommended)
+* `pyenet <http://code.google.com/p/pyenet/>`_
+
+
+Resources
+---------
+
+* Package on PyPI -- http://pypi.python.org/pypi/pygnetic
+* Repository on Bitbucket -- https://bitbucket.org/bluex/pygnetic
+* Documentation -- http://pygnetic.readthedocs.org
+* Development blog -- http://pygame-networking.blogspot.com
+
+
+Credits
+-------
+
+pygnetic is under development by Szymon Wróblewski <bluex0@gmail.com>
+as `GSoC 2012 <http://code.google.com/soc/>`_ project and mentored by
+René Dudfield <renesd@gmail.com>.
+
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`modindex`
+License
+=======
+
+Module is licensed by the same license as Pygame
+
+.. include:: ../LICENSE.txt
+   :literal:
 if "%SPHINXBUILD%" == "" (
 	set SPHINXBUILD=sphinx-build
 )
-set BUILDDIR=build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
-set I18NSPHINXOPTS=%SPHINXOPTS% source
+set BUILDDIR=../build/sphinx
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
 if NOT "%PAPER%" == "" (
 	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
 	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
Add a comment to this file

doc/source/_static/pygnetic.png

Removed
Old image

doc/source/api/index.rst

-:mod:`pygnetic` Package
-=======================
-
-.. automodule:: pygnetic
-
-   .. autofunction:: init([events[, event_val[, logging_lvl[, n_module[, s_module]]]]])
-   
-   .. autofunction:: register(name[, field_names[, **kwargs]])
-   
-      .. note:: It uses :data:`.message.message_factory`
-      
-   .. autoclass:: Client
-   
-   .. autoclass:: Server
-   
-   .. class :: Handler
-   
-      :class:`handler.Handler` binding.
-   
-   
-:mod:`client` Module
---------------------
-
-.. automodule:: pygnetic.client
-    
-   .. autoclass:: Client([conn_limit, [*args, **kwargs]])
-    
-      Example::
-      
-         client = pygnetic.client.Client()
-         connection = client.connect("localhost", 10000)
-         while True:
-            client.update()
-            
-      .. data:: message_factory
-         
-         Default :class:`~.message.MessageFactory` object used for new
-         connections. (default: :data:`.message.message_factory`)
-      
-      .. automethod:: connect(host, port[, message_factory[, **kwargs]])
-      
-      .. automethod:: update(self[, timeout])
-
-
-:mod:`connection` Module
-------------------------
-
-.. automodule:: pygnetic.connection
-    
-   .. autoclass:: Connection(parent, conn_obj, message_factory)
-      
-      Example::
-      
-         # assuming chat_msg message is already defined
-         connection.net_chat_msg('Tom', 'Test message')
-         # alternative
-         connection.send(chat_msg, 'Tom', 'Test message')
-         # or
-         connection.send('chat_msg', 'Tom', 'Test message')
-      
-      .. attribute:: parent
-      
-         :func:`Proxy <weakref.proxy>` to Client / Server instance
-         
-      .. attribute:: address
-      
-         Connection address
-         
-      .. attribute:: connected
-      
-         True if connected
-         
-      .. attribute:: data_sent
-      
-         Amount of data sent
-         
-      .. attribute:: data_received
-      
-         Amount of data received
-         
-      .. attribute:: messages_sent
-      
-         Amount of messages sent
-         
-      .. attribute:: messages_received
-      
-         Amount of messages received
-         
-      .. automethod:: add_handler(handler)
-      
-      .. automethod:: disconnect([*args])
-      
-      .. method:: net_message_name([\*args, \*\*kwargs])
-
-         Send ``message_name`` messagge to remote host.
-         
-         :param args: parameters used to initialize message object
-         :param kwargs: keyword parameters used to initialize message object
-         
-         It uses :meth:`__getattr__ <object.__getattr__>` mechanism to add
-         :meth:`net_message_name` :func:`partial <functools.partial>` method
-         to class and call it. Any subsequent call is realized by new method.
-      
-      .. automethod:: send(message[, *args, **kwargs])
-         
-
-
-:mod:`event` Module
--------------------
-
-.. automodule:: pygnetic.event
-   
-   .. data:: NETWORK
-
-   .. data:: NET_DISCONNECTED
-   
-   .. data:: NET_CONNECTED
-   
-   .. data:: NET_ACCEPTED
-   
-   .. data:: NET_RECEIVED
-   
-   Event attributes:
-   
-      Connected event
-         | ``type`` = :const:`NETWORK`
-         | ``net_type`` = :const:`NET_CONNECTED`
-         | ``connection`` -- connection
-      
-      Disconnected event
-         | ``type`` = :const:`NETWORK`
-         | ``net_type`` = :const:`NET_DISCONNECTED`
-         | ``connection`` -- connection
-      
-      Accepted event
-         | ``type`` = :const:`NETWORK`
-         | ``net_type`` = :const:`NET_ACCEPTED`
-         | ``connection`` -- connection
-      
-      Received event
-         | ``type`` = :const:`NETWORK`
-         | ``net_type`` = :const:`NET_RECEIVED`
-         | ``connection`` -- connection
-         | ``message`` -- received message
-         | ``msg_type`` -- message type
-   
-   Example::
-
-      for e in pygame.event.get():
-          if e.type == event.NETWORK:
-              if e.net_type == event.NET_CONNECTED:
-                  print 'connected'
-              elif e.net_type == event.NET_DISCONNECTED:
-                  print 'disconnected'
-              elif e.net_type == event.NET_RECEIVED:
-                  # assuming chat_msg message is already defined
-                  if e.msg_type == chat_msg:
-                      print '%s: %s' % (e.message.player, e.message.msg)
-                  else:
-                      print 'received:', e.message
-   
-   .. note::
-      
-      To use events you need to enable them with :func:`.init`
-   
-   .. warning::
-   
-      If you plan to change value of :const:`NETWORK` with
-      :func:`.init`, then use:: 
-         
-         import pygnetic.event as event
-         # rather than
-         # from pygnetic.event import NETWORK
-
-
-:mod:`handler` Module
----------------------
-
-.. automodule:: pygnetic.handler
-
-   .. autoclass:: Handler
-   
-      .. attribute:: connection
-      
-         :func:`Proxy <weakref.proxy>` to :class:`~.connection.Connection`
-         derived class instance
-         
-      .. attribute:: server
-      
-         :func:`Proxy <weakref.proxy>` to :class:`~.server.Server`
-         derived class instance   
-      
-      .. method:: net_message_name(message[, **kwargs])
-      
-         Called when ``message_name`` message is received
-         
-         :param message: received message
-         :param kwargs:
-            additional keyword arguments from :term:`network adapter`
-      
-      .. automethod:: on_connect
-      
-      .. automethod:: on_disconnect
-      
-      .. automethod:: on_recive(message[, **kwargs])
-
-
-:mod:`message` Module
----------------------
-
-.. automodule:: pygnetic.message
-
-   .. data:: message_factory
-      
-      Default instance of :class:`MessageFactory` used by other modules.
-   
-   .. autoclass:: MessageFactory([s_adapter])
-   
-      Example::
-      
-         chat_msg = MessageFactory.register('chat_msg', ('player', 'msg'))
-         data = MessageFactory.pack(chat_msg('Tom', 'Test message'))
-         message = MessageFactory.unpack(data)
-         player = message.player
-         msg = message.msg
-         
-      .. note::
-      
-         You can create more instances of :class:`MessageFactory` when you want
-         to separate messages for different connections in
-         :class:`~.client.Client`.
-      
-      .. automethod:: get_by_name
-      
-      .. automethod:: get_by_type
-      
-      .. automethod:: get_hash
-      
-      .. automethod:: get_params
-      
-      .. automethod:: get_type_id
-      
-      .. automethod:: pack
-      
-      .. automethod:: register(name[, field_names[, **kwargs]])
-      
-      .. automethod:: reset_context
-      
-      .. automethod:: set_frozen
-      
-      .. automethod:: unpack
-      
-      .. automethod:: unpack_all
-
-
-:mod:`server` Module
---------------------
-
-.. automodule:: pygnetic.server
-    
-   .. autoclass:: Server([host[, port[, conn_limit[, *args, **kwargs]]]])
-      
-      .. attribute:: address
-         
-         Server address.
-         
-      .. automethod:: connections([exclude])
-      
-      .. automethod:: handlers([exclude])
-      
-      .. automethod:: update([timeout])
-
-
-Small FAQ
-=========
-
-**Why I have to register message? Can't I just use dictionary to send it?**
-   :meth:`~.message.MessageFactory.register` creates a compact
-   data structure - :func:`namedtuple <collections.namedtuple>`, which contains
-   only essential data, reducing overall amount of data to send. Take a look at
-   example below and compare sizes of packed dictionary and structure created
-   by :class:`~.message.MessageFactory`.
-
-      >>> import msgpack
-      >>> m1 = msgpack.packb({'action':'chat_msg', 'player':'Tom', 'msg':'Test message'})
-      >>> m1, len(m1)
-      ('\x83\xa6action\xa8chat_msg\xa6player\xa3Tom\xa3msg\xacTest message', 45)
-      >>> import pygnetic as net
-      >>> net.init()
-      17:11:40 INFO     Using enet_adapter
-      17:11:40 INFO     Using msgpack_adapter
-      True
-      >>> chat_msg = net.register('chat_msg', ('player', 'msg'))
-      >>> m2 = net.message.message_factory.pack(chat_msg('Tom', 'Test message'))
-      >>> m2, len(m2)
-      ('\x93\x02\xa3Tom\xacTest message', 19)
-
-   The only drawback of this method is the need to register the same messages
-   in the same order in client and server.
-
-**Why order of registration messages is important?**
-   As You may noticed in previous example, there is no string with type of
-   message in packed data. That's because type is encoded as integer,
-   depending on order of registration.
-
-
-Glossary
-========
-
-.. glossary::
-   :sorted:
-
-   network adapter
-      class providing unified interface for different network libraries
-      
-   serialization adapter
-      class providing unified interface for different serialization libraries

doc/source/conf.py

-# -*- coding: utf-8 -*-
-#
-# pygnetic documentation build configuration file, created by
-# sphinx-quickstart on Sun Jun 17 20:09:12 2012.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.insert(0, os.path.abspath('../..'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
-extensions = ['sphinx.ext.autodoc',
-              'sphinx.ext.viewcode',
-              'sphinx.ext.intersphinx',
-              ]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'pygnetic'
-copyright = u'2012, Szymon Wróblewski'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-from pygnetic import __version__
-import distutils.version
-v = distutils.version.StrictVersion(__version__)
-# The short X.Y version.
-version = '.'.join(map(str, v.version[:2]))
-# The full version, including alpha/beta/rc tags.
-release = str(v)
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['build']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-intersphinx_mapping = {
-    'python': ('http://python.readthedocs.org/en/latest/', None),
-}
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-html_theme = 'default'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-html_logo = '_static/pygnetic.png'
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'pygneticdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
-  ('index', 'pygnetic.tex', u'Pygame network Documentation',
-   u'Szymon Wróblewski', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'pygnetic', u'pygnetic Documentation',
-     [u'Szymon Wróblewski'], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output ------------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-  ('index', 'pygnetic', u'pygnetic Documentation',
-   u'Szymon Wróblewski', 'pygnetic', 'One line description of project.',
-   'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-
-# -- Options for Epub output ---------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'pygnetic'
-epub_author = u'Szymon Wróblewski'
-epub_publisher = u'Szymon Wróblewski'
-epub_copyright = u'2012, Szymon Wróblewski'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True

doc/source/examples.rst

-Examples
-========
-
-.. literalinclude:: ../../test_server.py
-
-.. literalinclude:: ../../test_client_2.py

doc/source/index.rst

-pygnetic --- Easy networking in Pygame
-======================================
-
-**pygnetic** is a library designed to help in the development of
-network games and applications in `Pygame <http://www.pygame.org>`_.
-
-
-Features
---------
-
-* Two approaches to handle network events
-   * generating events in pygame queue
-   * using handler classes
-* Efficient packaging of data through the message system
-* Support for multiple network and serialization libraries
-
-
-Contents
---------
-
-.. toctree::
-   :maxdepth: 2
-   :glob:
-
-   api/index
-   examples
-   license
-
-
-Installation
-------------
-
-**pygnetic** can be installed with
-`windows installer <http://pypi.python.org/pypi/pygnetic/#downloads>`_
-or with `pip <http://www.pip-installer.org>`_::
-
-   pip install pygnetic
-
-
-Optional requirements
----------------------
-
-* `Message Pack <http://msgpack.org/>`_ (recommended)
-* `pyenet <http://code.google.com/p/pyenet/>`_
-
-
-Resources
----------
-
-* Package on PyPI -- http://pypi.python.org/pypi/pygnetic
-* Repository on Bitbucket -- https://bitbucket.org/bluex/pygnetic
-* Documentation -- http://pygnetic.readthedocs.org
-* Development blog -- http://pygame-networking.blogspot.com
-
-
-Credits
--------
-
-pygnetic is under development by Szymon Wróblewski <bluex0@gmail.com>
-as `GSoC 2012 <http://code.google.com/soc/>`_ project and mentored by
-René Dudfield <renesd@gmail.com>.
-
-
-Indices and tables
-------------------
-
-* :ref:`genindex`
-* :ref:`modindex`

doc/source/license.rst

-License
-=======
-
-Module is licensed by the same license as Pygame
-
-.. include:: ../../LICENSE.txt
-   :literal:
 [build_sphinx]
-source-dir = doc/source
-build-dir  = doc/build
+source-dir = doc
+build-dir  = build/sphinx
 all_files  = 1
 
 [upload_sphinx]
-upload-dir = doc/build/html
+upload-dir = build/sphinx/html
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from distutils.core import setup
+#from distutils.core import setup
+from setuptools import setup
 import pygnetic
 
 setup(
     packages=['pygnetic', 'pygnetic.network', 'pygnetic.serialization'],
     license=open('LICENSE.txt').readline().strip(),
     long_description=open('README.txt').read(),
+    test_suite='tests',
     classifiers=[
         'Development Status :: 3 - Alpha',
         'Environment :: Console',

tests/message_test.py

-if __name__ == '__main__':
-    import sys
-    import os
-    pkg_dir = os.path.dirname(os.path.abspath(__file__))
-    parent_dir, pkg_name = os.path.split(pkg_dir)
-    sys.path.insert(0, parent_dir)
-import unittest
-import pygnetic
-
-
-class MessageTests(unittest.TestCase):
-
-    def setUp(self):
-        pygnetic.serialization.select_adapter('msgpack')
-        self.message_factory = pygnetic.message.MessageFactory()
-
-    def test_register(self):
-        message_factory = pygnetic.message.MessageFactory()
-        name = 'test_01'
-        fields = ('name_01', 'name_02', 'name_03')
-        parameters = {'arg_1': 1, 'arg_2': 2, 'arg_3': 3}
-        test_01 = message_factory.register(name, fields, **parameters)
-        self.assertIsNotNone(test_01)
-        self.assertEqual(test_01.__name__, name)
-        self.assertTupleEqual(test_01._fields, fields)
-        self.assertDictEqual(message_factory.get_params(test_01), parameters)
-
-if __name__ == '__main__':
-    unittest.main(verbosity=2)

tests/serialization_test.py

-if __name__ == '__main__':
-    import sys
-    import os
-    pkg_dir = os.path.dirname(os.path.abspath(__file__))
-    parent_dir, pkg_name = os.path.split(pkg_dir)
-    sys.path.insert(0, parent_dir)
-import unittest
-import pygnetic
-
-
-class CommonTests(object):
-    def test_select_adapter(self):
-        pygnetic.serialization.select_adapter(self.adapter_lib_name)
-        self.assertEqual(pygnetic.serialization.selected_adapter,
-                         self.adapter,
-                         'incorrect selected adapter')
-        self.assertEqual(pygnetic.serialization.pack,
-                         self.adapter.pack,
-                         'incorrect selected adapter pack function')
-        self.assertEqual(pygnetic.serialization.unpack,
-                         self.adapter.unpack,
-                         'incorrect selected adapter unpack function')
-        self.assertEqual(pygnetic.serialization.unpacker,
-                         self.adapter.unpacker,
-                         'incorrect selected adapter unpacker class')
-
-    def test_get_adapter(self):
-        adapter = pygnetic.serialization.get_adapter(self.adapter_lib_name)
-        self.assertEqual(adapter, self.adapter,
-                         'incorrect selected adapter')
-
-
-class MsgpackAdapterTests(unittest.TestCase, CommonTests):
-    def setUp(self):
-        import pygnetic.serialization.msgpack_adapter as adapter
-        self.adapter = adapter
-        self.adapter_lib_name = 'msgpack'
-
-
-class JsonAdapterTests(unittest.TestCase, CommonTests):
-    def setUp(self):
-        import pygnetic.serialization.json_adapter as adapter
-        self.adapter = adapter
-        self.adapter_lib_name = 'json'
-
-
-if __name__ == '__main__':
-    unittest.main(verbosity=2)

tests/test_message.py

+if __name__ == '__main__':
+    import sys
+    import os
+    pkg_dir = os.path.dirname(os.path.abspath(__file__))
+    parent_dir, pkg_name = os.path.split(pkg_dir)
+    sys.path.insert(0, parent_dir)
+import unittest
+import pygnetic
+
+
+class MessageTests(unittest.TestCase):
+
+    def setUp(self):
+        pygnetic.serialization.select_adapter('json')
+        self.message_factory = pygnetic.message.MessageFactory()
+
+    @classmethod
+    def generate_msgs(cls, messages, fields, parameters):
+        message_factory = pygnetic.message.MessageFactory()
+        return message_factory, [
+            message_factory.register(
+                'test_%d' % (m + 1),
+                ['name_%d' % (f + 1) for f in range(fields)],
+                **{'arg_%d' % (a + 1) : (a + 1) for a in range(parameters)}
+            ) for m in range(messages)
+        ]
+
+    def test_register(self):
+        message_factory = pygnetic.message.MessageFactory()
+        name = 'test_01'
+        fields = ('name_01', 'name_02', 'name_03')
+        parameters = {'arg_1': 1, 'arg_2': 2, 'arg_3': 3}
+        test_01 = message_factory.register(name, fields, **parameters)
+        self.assertIsNotNone(test_01)
+        self.assertEqual(test_01.__name__, name)
+        self.assertTupleEqual(test_01._fields, fields)
+        self.assertDictEqual(message_factory.get_params(test_01), parameters)
+
+    def test_pack(self):
+        mf, msgs = self.generate_msgs(3, 3, 3)
+        data = list(range(1, 4))
+        for i, msg in enumerate(msgs):
+            self.assertEqual(
+                '[%s]' % ', '.join(str(d) for d in [i + 1] + data),
+                mf.pack(msg(*data))
+            )
+        with self.assertRaises(ValueError):
+            mf.pack('')
+
+    def test_unpack(self):
+        mf, msgs = self.generate_msgs(3, 3, 3)
+        data = list(range(1, 4))
+        for i, msg in enumerate(msgs):
+            self.assertTupleEqual(
+                mf.unpack('[%s]' % ', '.join(str(d) for d in [i + 1] + data)),
+                msg(*data)
+            )
+
+def suite():
+    return unittest.TestLoader().loadTestsFromTestCase(MessageTests)
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)

tests/test_serialization.py

+if __name__ == '__main__':
+    import sys
+    import os
+    pkg_dir = os.path.dirname(os.path.abspath(__file__))
+    parent_dir, pkg_name = os.path.split(pkg_dir)
+    sys.path.insert(0, parent_dir)
+import unittest
+import pygnetic
+
+
+class CommonTests(object):
+    def test_select_adapter(self):
+        pygnetic.serialization.select_adapter(self.adapter_lib_name)
+        self.assertEqual(pygnetic.serialization.selected_adapter,
+                         self.adapter,
+                         'incorrect selected adapter')
+        self.assertEqual(pygnetic.serialization.pack,
+                         self.adapter.pack,
+                         'incorrect selected adapter pack function')
+        self.assertEqual(pygnetic.serialization.unpack,
+                         self.adapter.unpack,
+                         'incorrect selected adapter unpack function')
+        self.assertEqual(pygnetic.serialization.unpacker,
+                         self.adapter.unpacker,
+                         'incorrect selected adapter unpacker class')
+
+    def test_get_adapter(self):
+        adapter = pygnetic.serialization.get_adapter(self.adapter_lib_name)
+        self.assertEqual(adapter, self.adapter,
+                         'incorrect selected adapter')
+
+
+class MsgpackAdapterTests(unittest.TestCase, CommonTests):
+    def setUp(self):
+        import pygnetic.serialization.msgpack_adapter as adapter
+        self.adapter = adapter
+        self.adapter_lib_name = 'msgpack'
+
+
+class JsonAdapterTests(unittest.TestCase, CommonTests):
+    def setUp(self):
+        import pygnetic.serialization.json_adapter as adapter
+        self.adapter = adapter
+        self.adapter_lib_name = 'json'
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.