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):
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
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",
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,
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,