Action: Don't need the owner in the constructor. Factory function to create a child.
[python-bulletml.git] / setup.py
index 1b383c2..54a86d1 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,21 @@
 import glob
 import os
 import shutil
+import sys
+
+from distutils.core import setup, Command, Extension
+
+try:
+    from Pyrex.Distutils import build_ext
+except ImportError:
+    from distutils.command.build_ext import build_ext
+    ext_modules = []
+else:
+    ext_modules = [Extension(
+        'bulletml._collision', [os.path.join('bulletml', '_collision.pyx')])]
 
-from distutils.core import setup
 from distutils.command.clean import clean as distutils_clean
+from distutils.command.sdist import sdist as distutils_sdist
 
 class clean(distutils_clean):
     def run(self):
@@ -22,8 +34,8 @@ class clean(distutils_clean):
         for pathname, dirs, files in os.walk(os.path.dirname(__file__)):
             for filename in filter(should_remove, files):
                 try: os.unlink(os.path.join(pathname, filename))
-                except EnvironmentError, err:
-                    print str(err)
+                except EnvironmentError as err:
+                    print(str(err))
 
         try: os.unlink("MANIFEST")
         except OSError: pass
@@ -33,10 +45,77 @@ class clean(distutils_clean):
              if os.path.isdir(path):
                  shutil.rmtree(path)
 
+class coverage_cmd(Command):
+    description = "generate test coverage data"
+    user_options = []
+
+    def initialize_options(self):
+        pass
+    
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        import trace
+        tracer = trace.Trace(
+            count=True, trace=False,
+            ignoredirs=[sys.prefix, sys.exec_prefix])
+        def run_tests():
+            import bulletml
+            try:
+                reload(bulletml)
+            except NameError:
+                pass
+            self.run_command("test")
+        tracer.runfunc(run_tests)
+        results = tracer.results()
+        coverage = os.path.join(os.path.dirname(__file__), "coverage")
+        results.write_results(show_missing=True, coverdir=coverage)
+        map(os.unlink, glob.glob(os.path.join(coverage, "[!b]*.cover")))
+        try: os.unlink(os.path.join(coverage, "..setup.cover"))
+        except OSError: pass
+
+        total_lines = 0
+        bad_lines = 0
+        for filename in glob.glob(os.path.join(coverage, "*.cover")):
+            lines = open(filename, "rU").readlines()
+            total_lines += len(lines)
+            bad_lines += len(
+                [line for line in lines if
+                 (line.startswith(">>>>>>") and
+                  "finally:" not in line and '"""' not in line)])
+        pct = 100.0 * (total_lines - bad_lines) / float(total_lines)
+        print("Coverage data written to %s (%d/%d, %0.2f%%)" % (
+            coverage, total_lines - bad_lines, total_lines, pct))
+
+class sdist(distutils_sdist):
+    def run(self):
+        self.run_command("test")
+        distutils_sdist.run(self)
+
+class test_cmd(Command):
+    description = "run automated tests"
+    user_options = [
+        ("to-run=", None, "list of tests to run (default all)"),
+        ]
+
+    def initialize_options(self):
+        self.to_run = []
+        self.quick = False
+
+    def finalize_options(self):
+        if self.to_run:
+            self.to_run = self.to_run.split(",")
+
+    def run(self):
+        import tests
+        if tests.unit(self.to_run):
+            raise SystemExit("Test failures are listed above.")
+
 if __name__ == "__main__":
-    from bulletml import VERSION_STRING
-    setup(cmdclass=dict(clean=clean),
-          name="python-bulletml", version=VERSION_STRING,
+    setup(cmdclass=dict(clean=clean, test=test_cmd, coverage=coverage_cmd,
+                        sdist=sdist, build_ext=build_ext),
+          name="python-bulletml", version="1",
           url="http://code.google.com/p/python-bulletml/",
           description="parse and run BulletML scripts",
           author="Joe Wreschnig",
@@ -45,6 +124,7 @@ if __name__ == "__main__":
           packages=["bulletml"],
           data_files=glob.glob("examples/*/*.xml") + ["examples/template.xml"],
           scripts=["bulletml-runner", "bulletml-to-bulletyaml"],
+          ext_modules=ext_modules,
           long_description="""\
 BulletML is the Bullet Markup Language. BulletML can describe the
 barrage of bullets in shooting games. (For example Progear, Psyvariar,
@@ -55,6 +135,9 @@ renderer-agnostic.
 In addition to the standard BulletML XML format, this module supports
 an equivalent YAML format.
 
+Finally, two simple collision routines are provided, bulletml.overlaps
+for stationary circles and bulletml.collides for moving circles.
+
 A sample renderer for Pygame is included.
 
 More information is available at the BulletML homepage,