8 from distutils
.core
import setup
, Command
, Extension
9 from distutils
.command
.clean
import clean
as distutils_clean
10 from distutils
.command
.sdist
import sdist
as distutils_sdist
13 class clean(distutils_clean
):
15 # In addition to what the normal clean run does, remove pyc
16 # and pyo and backup files from the source tree.
17 distutils_clean
.run(self
)
19 def should_remove(filename
):
20 if (filename
.lower()[-4:] in [".pyc", ".pyo"]
21 or filename
.endswith("~")
22 or (filename
.startswith("#")
23 and filename
.endswith("#"))):
27 for pathname
, dirs
, files
in os
.walk(os
.path
.dirname(__file__
)):
28 for filename
in filter(should_remove
, files
):
30 os
.unlink(os
.path
.join(pathname
, filename
))
31 except EnvironmentError as err
:
39 for base
in ["coverage", "build", "dist"]:
40 path
= os
.path
.join(os
.path
.dirname(__file__
), base
)
41 if os
.path
.isdir(path
):
45 class coverage_cmd(Command
):
46 description
= "generate test coverage data"
49 def initialize_options(self
):
52 def finalize_options(self
):
58 count
=True, trace
=False,
59 ignoredirs
=[sys
.prefix
, sys
.exec_prefix
])
67 self
.run_command("test")
69 tracer
.runfunc(run_tests
)
70 results
= tracer
.results()
71 coverage
= os
.path
.join(os
.path
.dirname(__file__
), "coverage")
72 results
.write_results(show_missing
=True, coverdir
=coverage
)
73 map(os
.unlink
, glob
.glob(os
.path
.join(coverage
, "[!b]*.cover")))
75 os
.unlink(os
.path
.join(coverage
, "..setup.cover"))
81 for filename
in glob
.glob(os
.path
.join(coverage
, "*.cover")):
82 lines
= open(filename
, "rU").readlines()
83 total_lines
+= len(lines
)
85 [line
for line
in lines
if
86 (line
.startswith(">>>>>>") and
87 "finally:" not in line
and '"""' not in line
)])
88 pct
= 100.0 * (total_lines
- bad_lines
) / float(total_lines
)
89 print("Coverage data written to %s (%d/%d, %0.2f%%)" % (
90 coverage
, total_lines
- bad_lines
, total_lines
, pct
))
93 class sdist(distutils_sdist
):
95 self
.run_command("test")
96 distutils_sdist
.run(self
)
99 class test_cmd(Command
):
100 description
= "run automated tests"
102 ("to-run=", None, "list of tests to run (default all)"),
105 def initialize_options(self
):
109 def finalize_options(self
):
111 self
.to_run
= self
.to_run
.split(",")
115 if tests
.unit(self
.to_run
):
116 raise SystemExit("Test failures are listed above.")
118 if __name__
== "__main__":
119 setup(cmdclass
=dict(clean
=clean
, test
=test_cmd
, coverage
=coverage_cmd
,
121 name
="python-bulletml", version
="3",
122 url
="https://yukkurigames.com/python-bulletml/",
123 description
="parse and run BulletML scripts",
124 author
="Joe Wreschnig",
125 author_email
="joe.wreschnig@gmail.com",
127 packages
=["bulletml"],
128 data_files
=glob
.glob("examples/*/*.xml") + ["examples/template.xml"],
129 scripts
=["bulletml-runner", "bulletml-to-bulletyaml"],
130 ext_modules
=[Extension(
131 'bulletml._collision',
132 [os
.path
.join('bulletml', '_collision.c')])],
133 long_description
="""\
134 BulletML is the Bullet Markup Language. BulletML can describe the
135 barrage of bullets in shooting games. (For example Progear, Psyvariar,
136 Gigawing2, G DARIUS, XEVIOUS, ...) This module parses and executes
137 BulletML scripts in Python. All data structures in it are
138 renderer-agnostic. A sample renderer for Pygame is included. The full
139 API documentation is contained in its Python docstrings.
141 In addition to the standard BulletML XML format, this module supports
142 an equivalent YAML format. For convenience, two simple collision
143 routines are provided, bulletml.overlaps for stationary circles and
144 bulletml.collides for moving circles.
146 More information is available at the BulletML homepage,
147 http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html, or the
148 python-bulletml homepage, https://yukkurigames.com/python-bulletml/.