Repository: coin-or/pulp

Issue:
update all examples to python 3
and take out the photo from the wedding example.

Discussion:

Patch:
diff --git a/.gitignore b/.gitignore
index fae935c..f215a18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,4 +59,7 @@ target/
 py-ve*
 
 #cloud9
-.c9
\ No newline at end of file
+.c9
+
+#pycharm
+.idea/
\ No newline at end of file
diff --git a/README.md b/README.rst
similarity index 62%
rename from README.md
rename to README.rst
index 27d9e3f..fe219f0 100644
--- a/README.md
+++ b/README.rst
@@ -1,24 +1,33 @@
-# pulp [![Build Status](https://travis-ci.org/coin-or/pulp.svg?branch=master)](https://travis-ci.org/coin-or/pulp)
+pulp
+**************************
+.. image:: https://travis-ci.org/coin-or/pulp.svg?branch=master
+    :target: https://travis-ci.org/coin-or/pulp
+
+.. highlight:: python
 
 PuLP is an LP modeler written in Python. PuLP can generate MPS or LP files
 and call GLPK[1], COIN CLP/CBC[2], CPLEX[3], and GUROBI[4] to solve linear
 problems.
 
-## Installation
+Installation
+================
 
-The easiest way to install pulp is via [PyPi](https://pypi.python.org/pypi/PuLP)
+The easiest way to install pulp is via `PyPi <https://pypi.python.org/pypi/PuLP>`_
 
-If pip is available on your system:
+If pip is available on your system::
 
-     $ pip install pulp
+     pip install pulp
 
 Otherwise follow the download instructions on the PyPi page.
 On Linux and OSX systems the tests must be run to make the default
 solver executable.
 
-     $ sudo pulptest
+::
+
+     sudo pulptest
 
-## Examples
+Examples
+================
 
 See the examples directory for examples.
 
@@ -26,49 +35,51 @@ PuLP requires Python >= 2.6.
 
 The examples use the default solver (CBC), to use other solvers they must be available.
 
-# Documentation
-Documentation is found on https://pythonhosted.org/PuLP/.
+Documentation
+================
 
+Documentation is found on https://coin-or.github.io/pulp/.
 
-Use LpVariable() to create new variables. To create a variable 0 <= x <= 3
 
-     >>> x = LpVariable("x", 0, 3)
+Use LpVariable() to create new variables. To create a variable 0 <= x <= 3::
 
-To create a variable 0 <= y <= 1
+     x = LpVariable("x", 0, 3)
 
-     >>> y = LpVariable("y", 0, 1)
+To create a variable 0 <= y <= 1::
 
-Use LpProblem() to create new problems. Create "myProblem"
+     y = LpVariable("y", 0, 1)
 
-     >>> prob = LpProblem("myProblem", LpMinimize)
+Use LpProblem() to create new problems. Create "myProblem"::
+
+     prob = LpProblem("myProblem", LpMinimize)
 
 Combine variables to create expressions and constraints, then add them to the
-problem.
+problem::
 
-     >>> prob += x + y <= 2
+     prob += x + y <= 2
 
 If you add an expression (not a constraint), it will
-become the objective.
+become the objective::
 
-     >>> prob += -4*x + y
+     prob += -4*x + y
 
-To solve with the default included solver
+To solve with the default included solver::
 
-     >>> status = prob.solve()
+     status = prob.solve()
 
-To use another sovler to solve the problem.
+To use another sovler to solve the problem::
 
-     >>> status = prob.solve(GLPK(msg = 0))
+     status = prob.solve(GLPK(msg = 0))
 
-Display the status of the solution
+Display the status of the solution::
 
-     >>> LpStatus[status]
-     'Optimal'
+     LpStatus[status]
+     > 'Optimal'
 
-You can get the value of the variables using value(). ex:
+You can get the value of the variables using value(). ex::
 
-     >>> value(x)
-     2.0
+     value(x)
+     > 2.0
 
 Exported Classes:
 
@@ -94,6 +105,7 @@ pulp-or-discuss@googlegroups.com
      See the LICENSE file for copyright information.
 
 References:
+
 [1] http://www.gnu.org/software/glpk/glpk.html
 [2] http://www.coin-or.org/
 [3] http://www.cplex.com/
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..edf3644
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,25 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SOURCEDIR     = source
+BUILDDIR      = ./../../pulp-or-docs
+PDFBUILDDIR   = /tmp
+PDF           = ../manual.pdf
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+buildandcommithtml: html latexpdf
+
+    cd $(BUILDDIR)/html; git add . ; git commit -m "rebuilt docs"; git push origin gh-pages
\ No newline at end of file
diff --git a/doc/make.bat b/doc/make.bat
new file mode 100644
index 0000000..e3a4787
--- /dev/null
+++ b/doc/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=./../../pulp-or-docs
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
diff --git a/doc/source/CaseStudies/a_set_partitioning_problem.rst b/doc/source/CaseStudies/a_set_partitioning_problem.rst
index 30343e6..7d4d0de 100644
--- a/doc/source/CaseStudies/a_set_partitioning_problem.rst
+++ b/doc/source/CaseStudies/a_set_partitioning_problem.rst
@@ -12,13 +12,7 @@ for a wedding. To model this problem the tables are modelled as the partitions
 and the guests invited to the wedding are modelled as the elements of S. The 
 wedding planner wishes to maximise the total happiness of all of the tables. 
 
-.. image:: images/wedding_seating.jpg
-
-.. raw:: html
-
-    <div xmlns:cc="http://creativecommons.org/ns#" about="http://www.flickr.com/photos/71463577@N00/3735357685"><a rel="cc:attributionURL" href="http://www.flickr.com/photos/mbphotography/">http://www.flickr.com/photos/mbphotography/</a> / <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.0/">CC BY-NC-ND 2.0</a></div>
-
-A set partitioning problem may be modelled by explicitly enumerating each 
+A set partitioning problem may be modelled by explicitly enumerating each
 possible subset. Though this approach does become intractable for large numbers
 of items (without using column generation) it does have the advantage that the
 objective function co-efficients for the partitions can be non-linear 
diff --git a/doc/source/CaseStudies/a_sudoku_problem.rst b/doc/source/CaseStudies/a_sudoku_problem.rst
index cb02b57..2166a6e 100644
--- a/doc/source/CaseStudies/a_sudoku_problem.rst
+++ b/doc/source/CaseStudies/a_sudoku_problem.rst
@@ -135,7 +135,7 @@ The problem is written to an LP file, solved using CPLEX (due to CPLEX's simple
 Instead of printing out all 729 of the binary problem variables and their respective values, it is more meaningful to draw the solution in a text file. The code also puts lines inbetween every third row and column to make the solution easier to read. The sudokuout.txt file is created in the same folder as the .py file.
 
 .. literalinclude:: ../../../examples/Sudoku1.py
-    :lines: 92-108
+    :lines: 90-108
 
 A note of the location of the solution is printed to the solution
 
diff --git a/doc/source/CaseStudies/index.rst b/doc/source/CaseStudies/index.rst
index 1a05eaa..5f99ab6 100644
--- a/doc/source/CaseStudies/index.rst
+++ b/doc/source/CaseStudies/index.rst
@@ -9,6 +9,7 @@
     a_blending_problem
     a_set_partitioning_problem
     a_sudoku_problem
+    a_transportation_problem
 
 Indices and tables
 ==================
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 191a298..f11ea56 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -22,8 +22,9 @@ sys.path.insert(0,os.path.abspath('../src/pulp/'))
 
 # 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.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig', 'sphinx.ext.autosummary']
-
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 
+'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 
+'sphinx.ext.ifconfig', 'sphinx.ext.autosummary', 'sphinx.ext.mathjax']
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
 
@@ -72,6 +73,11 @@ version = release[:3]
 # for source files.
 exclude_trees = []
 
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
 # The reST default role (used for this markup: `text`) to use for all documents.
 #default_role = None
 
@@ -97,13 +103,19 @@ pygments_style = 'sphinx'
 
 # The theme to use for HTML and HTML Help pages.  Major themes that come with
 # Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'default'
+# html_theme = 'default'
+html_theme = 'alabaster'
 
 # 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 = {}
-
+html_theme_options = {
+    'fixed_sidebar': True, 
+    'github_banner': True,
+    'show_powered_by': False,
+    'github_user': 'coin-or',
+    'github_repo': 'pulp'}
 # Add any paths that contain custom themes here, relative to this directory.
 #html_theme_path = []
 
@@ -201,4 +213,4 @@ latex_documents = [
 
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
+intersphinx_mapping = {'http://docs.python.org/3': None}
diff --git a/examples/CGcolumnwise.py b/examples/CGcolumnwise.py
index a46ba3d..974ddb6 100644
--- a/examples/CGcolumnwise.py
+++ b/examples/CGcolumnwise.py
@@ -70,10 +70,10 @@ def addPatterns(obj,constraints,newPatterns):
         for j,k in zip(i,Pattern.lenOpts):
             lsum += j * int(k)
         if lsum > Pattern.totalRollLength:
-            raise "Length Options too large for Roll"
+            raise("Length Options too large for Roll")
 
         # The number of rolls of each length in each new pattern is printed
-        print "P"+str(Pattern.numPatterns),"=",i
+        print("P"+str(Pattern.numPatterns),"=",i)
 
         # The patterns are instantiated as Pattern objects
         Patterns += [Pattern("P" + str(Pattern.numPatterns),i)]
diff --git a/examples/SpongeRollProblem5.py b/examples/SpongeRollProblem5.py
index b64ec5d..ec55530 100644
--- a/examples/SpongeRollProblem5.py
+++ b/examples/SpongeRollProblem5.py
@@ -5,7 +5,7 @@ Authors: Antony Phillips,  Dr Stuart Mitchell  2008
 """
 
 # Import Column Generation functions
-from CG import *
+from .CG import *
 
 # The roll data is created
 rollData = {#Length Demand SalePrice
diff --git a/examples/SpongeRollProblem6.py b/examples/SpongeRollProblem6.py
index 1a39ec0..5de7287 100644
--- a/examples/SpongeRollProblem6.py
+++ b/examples/SpongeRollProblem6.py
@@ -5,7 +5,7 @@ Authors: Antony Phillips,  Dr Stuart Mitchell  2008
 """
 
 # Import Column Generation functions
-from CGcolumnwise import *
+from .CGcolumnwise import *
 
 # The Master Problem is created
 prob, obj, constraints = createMaster()
diff --git a/setup.py b/setup.py
index e27fa9b..89f8566 100644
--- a/setup.py
+++ b/setup.py
@@ -8,6 +8,8 @@ from ez_setup import use_setuptools
 use_setuptools()
 from setuptools import setup
 
+readme_name = 'README.rst'
+Description = open(readme_name).read()
 
 License = open('LICENSE').read()
 
@@ -16,7 +18,7 @@ version_dict = {}
 exec(open('src/pulp/constants.py').read(), version_dict)
 VERSION = version_dict['VERSION']
 
-with open("README.md", "r") as fh:
+with open(readme_name, "r") as fh:
     long_description = fh.read()
 
 setup(name="PuLP",
diff --git a/src/pulp/amply.py b/src/pulp/amply.py
index 85034d4..70ffbcc 100644
--- a/src/pulp/amply.py
+++ b/src/pulp/amply.py
@@ -66,7 +66,7 @@ else:
     from pyparsing import alphas, nums, alphanums, delimitedList, oneOf
     from pyparsing import Combine, Dict, Forward, Group, Literal, NotAny
     from pyparsing import OneOrMore, Optional, ParseResults, QuotedString
-    from pyparsing import StringEnd, Suppress, Word, ZeroOrMore
+    from pyparsing import StringEnd, Suppress, Word, ZeroOrMore, SkipTo, lineEnd
 
     from itertools import chain
 
@@ -709,7 +709,7 @@ else:
     stmts = set_stmt | set_def_stmt | param_stmt | param_def_stmt | \
             param_tabbing_stmt
     grammar = ZeroOrMore(stmts) + StringEnd()
-
+    grammar.ignore("#" + SkipTo(lineEnd))
 
     class Amply(object):
         """
diff --git a/src/pulp/pulp.py b/src/pulp/pulp.py
index 97794e9..73fa01f 100644
--- a/src/pulp/pulp.py
+++ b/src/pulp/pulp.py
@@ -1106,6 +1106,9 @@ class LpProblem(object):
                 or :data:`~pulp.constants.LpMaximize`.
         :return: An LP Problem
         """
+        if ' ' in name:
+            warnings.warn("Spaces are not permitted in the name. Converted to '_'")
+            name = name.replace(" ", "_")
         self.objective = None
         self.constraints = _DICT_TYPE()
         self.name = name


Test patch:
diff --git a/tests/amply_tests.py b/tests/amply_tests.py
index c6a4aa9..c9229ec 100644
--- a/tests/amply_tests.py
+++ b/tests/amply_tests.py
@@ -501,4 +501,22 @@ def test_tuple_param():
     assert result[2,3] == 4
     assert result[3,4] == 5
 
+def test_comment():
+    result = Amply(
+        """
+        # a comment
+        set elem dimen 2;
+        param foo{elem};
+        param foo :=
+            1   2   3
+            2   3   4
+            3   4   5
+        ;
+        """
+    )['foo']
+
+    f = result[1,2]
+    assert f == 3
+    assert result[2,3] == 4
+    assert result[3,4] == 5
 
diff --git a/tests/test_examples.py b/tests/test_examples.py
new file mode 100644
index 0000000..e84e366
--- /dev/null
+++ b/tests/test_examples.py
@@ -0,0 +1,15 @@
+import os
+import importlib
+
+
+def test_examples(examples_dir='../examples'):
+    files = os.listdir(examples_dir)
+    for f_name in files:
+        if os.path.isdir(f_name):
+            continue
+        _f_name = 'examples.' + os.path.splitext(f_name)[0]
+
+        importlib.import_module(_f_name)
+
+if __name__ == '__main__':
+    test_examples('../examples')
\ No newline at end of file