Xonotic Map Manager’s documentation¶
A command-line package manager for the xonotic-map-repository project.

Features
- Quickly install maps from the command-line
- Discovery and optional addition of your existing maps to XMM’s library
- Repository-less install of map packages from a URL
- Multi-Server support (track different maps per server)
- Multi-repo support
- Plugin system
- Developer API, use xmm as a module
Get Started
Intro¶
Xonotic Map Manager is the command-line package manager component of the xonotic-map-repository project. Whether you’re a server admin looking to manage map lists, or a player trying to learn more about their map collection, xmm
is a tool to help you do this quickly and efficiently.
Use it like apt
:
xmm update
xmm install eggandscrambled.pk3
xmm list
If you get stuck, try using a xmm -h
, or reference the Usage page.
By default, the unofficial, general purpose Xonotic map repository, xonotic.co, is enabled. Advanced users can add additional repositories and/or host their own.
Installation¶
Requirements¶
- Python 3
Debian/Ubuntu¶
If you do not already have pip and setuptools for Python3:
sudo apt install python3-pip python3-setuptools
Install¶
Install using pip:
pip3 install xmm --user
If you get an error trying to run xmm
, you probably need $HOME/.local/bin
in your path, put the following in your ~/.bashrc
or ~/.zshrc
etc:
export PATH=$PATH:$HOME/.local/bin
Alternatively, install the development version manually with setuptools:
git clone https://github.com:z/xonotic-map-manager.git
cd xonotic-map-manager
python3 setup.py install
Configuration¶
Core¶
The defaults should work out of the box, if you want to make changes, edit the ~/.xmm.ini
file.
# This file is read from ~/.xmm.ini, make sure that's where you are editing it
[xmm]
# Where should xmm manage maps?
target_dir = ~/.xonotic/data/
# Default repo if no sources specified
download_url = http://dl.xonotic.co/
api_data_url = http://xonotic.co/resources/data/maps.json
api_data_file = ~/.xmm/maps.json
# This is only preference
use_curl = False
# configuration of servers to use with multiple servers
servers_config = ~/.xmm/servers.json
# configuration of repositories
sources_config = ~/.xmm/sources.json
Logging¶
Logging can be configured in ~/.xmm/xmm.logging.ini
, again, the defaults should be sufficient.
# ~/.xmm/xmm.logging.ini
[loggers]
keys = root
[logger_root]
level = NOTSET
handlers = stream, info
[handlers]
keys = stream, info
[handler_stream]
class = StreamHandler
args = (sys.stdout,)
level = ERROR
formatter = generic
[handler_debug]
class = handlers.RotatingFileHandler
formatter = generic
level = DEBUG
args = ('%(log_filename)s', 'a', 50000000, 5)
[handler_info]
class = handlers.RotatingFileHandler
formatter = generic
level = INFO
args = ('%(log_filename)s', 'a', 50000000, 5)
[formatters]
keys = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
class = logging.Formatter
Multi-Server¶
xmm can facilitate the management of multiple servers with ~/.xmm/servers.json
which defines the configure of settings, example below:
{
"myserver1": {
"target_dir": "~/.xonotic/myserver1/data/",
"library": "~/.xmm/myserver1/library.json",
"sources": "~/.xmm/sources.json"
},
"myserver2": {
"target_dir": "~/.xonotic/myserver2/data/",
"library": "~/.xmm/myserver2/library.json",
"sources": "~/.xmm/myserver2/sources.json"
}
}
Multi-repo¶
xmm can use multiple repositories, edit the ~/.xmm/sources.json
file to configure them, example below:
{
"default": {
"download_url": "http://dl.xonotic.co/",
"api_data_file": "~/.xmm/maps.json",
"api_data_url": "http://xonotic.co/resources/data/maps.json"
}
}
Usage¶
Basic Usage¶
CLI help docs for xmm
:
usage: xmm [-h] [--version] [-S [SERVER]] [-T [TARGET]] [-R [REPOSITORY]]
{search,install,remove,discover,list,show,export,servers,repos,update,hello}
...
Xonotic Map Manager is a tool to help manage Xonotic maps
positional arguments:
{search,install,remove,discover,list,show,export,servers,repos,update,hello}
search search for maps based on bsp names
install install a map from the repository, or specify a URL.
remove remove based on pk3 name
discover discover packages in a target directory
list list locally installed packages
show show details of remote or locally installed packages
export export locally managed packages to a file
servers subcommands on servers described in servers.json
repos subcommands on repos described in sources.json
update update sources json
hello hello is an example plugin
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
-S [SERVER], --server [SERVER]
target server as defined in servers.json
-T [TARGET], --target [TARGET]
target directory
-R [REPOSITORY], --repository [REPOSITORY]
repository to use (defaults to all available)
Searching¶
by bsp name:
xmm search snowdance
Searching for packages with the following criteria:
bsp: snowdance
---
snowdance2.pk3 [snowdance2]
http://dl.xonotic.co/snowdance2.pk3
snowdance_xon.pk3 [snowdance2]
http://dl.xonotic.co/snowdance_xon.pk3
---
Total packages found: 2
with pk3 name and detailed results:
xmm search --pk3 bloodrage_v2.pk3 --long
Using repo 'default'
Searching for packages with the following criteria:
pk3: bloodrage_v2.pk3
---
pk3: bloodrage_v2.pk3
bsp: bloodrage_v2
title: Bloodrage
description: Small, brutal and violent 1on1 map
author: Cortez and FruitieX
shasum: 488b05976e73456bf6f9833e353f72d3a8d0cbce
shasum: bloodrage_v2.pk3
date: 2009-10-17
size: 1MB
dl: http://dl.xonotic.co/bloodrage_v2.pk3
---
Total packages found: 1
Inline help is available on all sub-commands:
xmm search -h
usage: xmm search [-h] [--gametype [GAMETYPE]] [--pk3 [PK3]] [--title [TITLE]]
[--author [AUTHOR]] [--shasum [SHASUM]] [--long] [--short]
[--color]
[string]
positional arguments:
string bsp name found in a package, works on packages with
many bsps
optional arguments:
-h, --help show this help message and exit
--gametype [GAMETYPE]
filter by gametype
--pk3 [PK3] filter by pk3 name
--title [TITLE] filter by title
--author [AUTHOR] filter by author
--shasum [SHASUM] filter by shasum
--long, -l show long format
--short, -s show short format
--color, -c highlight search term in results
Installing from the repository¶
Installing a new pk3:
xmm install snowdance_xon.pk3
Installing map: snowdance_xon.pk3
...100%, 5 MB, 2438 KB/s, 2 seconds passed. Done.
You will be prompted to overwrite an existing pk3:
xmm install snowdance_xon.pk3
Installing map: snowdance_xon.pk3
snowdance_xon.pk3 already exists.
continue? [y/N] N
Canceled.
You cannot install a pk3 that doesn’t existent in the repo:
Installing map: fake.pk3
package does not exist in the repository. cannot install.
Example below is also showing the use of curl instead of python’s urllib if you prefer:
xmm install http://somerepo.org/snowdance2.pk3
Adding map: http://somerepo.org/snowdance2.pk3
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5530k 100 5530k 0 0 205k 0 0:00:26 0:00:26 --:--:-- 179k
Done.
You can install from any URL (buy lack detailed meta information about maps):
xmm install http://somerepo.org/some-other-map.pk3
Adding map: http://somerepo.org/snowdance2.pk3
...100%, 5 MB, 2438 KB/s, 2 seconds passed. Done.
Removing¶
Remove a map:
xmm remove snowdance2.pk3
Removing map: snowdance2.pk3
Done.
You cannot remove a map that doesn’t exist:
xmm remove snowdance2.pk3
Removing package: snowdance_xon.pk3
package does not exist or is not tracked. try removing using full path if not tracked.
Discover¶
You can pulled additional meta information about pk3s and verify their shasums against the repo with the discover command.
A summary of discovered packages:
xmm -S myserver1 discover
sxb1_testing_6.pk3 [sxb1_-1, sxb1_-2, sxb1_-3, sxb1_1-1, sxb1_1-2, sxb1_1-3, sxb1_1-4, sxb1_2-1, sxb1_2-2, sxb1_2-3, sxb1_2-4, sxb1_3-1, sxb1_3-2, sxb1_3-3, sxb1_3-4, sxb1_4-1, sxb1_4-2, sxb1_4-3, sxb1_4-4, sxb1_5-1, sxb1_5-2, sxb1_5-3, sxb1_5-4, sxb1_6-1, sxb1_6-2, sxb1_6-3, sxb1_6-4, sxb1_7-1, sxb1_7-2, sxb1_7-3, sxb1_7-4, sxb1_8-1, sxb1_8-2, sxb1_8-3, sxb1_8-4]
http://dl.xonotic.co/sxb1_testing_6.pk3
bloodprisonctf.pk3 [bloodprisonctf]
http://dl.xonotic.co/bloodprisonctf.pk3
bloodprisonctf.pk3 hash does not match repository's
gasoline_02.pk3 [gasoline_02, gasoline_3teams_02, gasoline_4teams_02, gasoline_noteams_02]
http://dl.xonotic.co/gasoline_02.pk3
testie3.pk3 [testie3]
http://dl.xonotic.co/testie3.pk3
map-derail_v1r5.pk3 [derail_v1r5]
http://dl.xonotic.co/map-derail_v1r5.pk3
map-derail_v1r5.pk3 hash does not match repository's
disarray_v1r2.pk3 [disarray_v1r2]
http://dl.xonotic.co/disarray_v1r2.pk3
eggandscrambled.pk3 [eggandscrambled]
http://dl.xonotic.co/eggandscrambled.pk3
Add discovered maps:
xmm -S myserver1 discover --add
List Map Packages¶
simple list:
xmm list
gasoline_02.pk3 [gasoline_02, gasoline_3teams_02, gasoline_4teams_02, gasoline_noteams_02]
http://dl.xonotic.co/gasoline_02.pk3
dance.pk3 [dance]
http://dl.xonotic.co/dance.pk3
Total packages found: 2
detailed list:
xmm list -l
pk3: gasoline_02.pk3
bsp: gasoline_02
title: Gasoline Powered
description: Retextured and glowy
author: FruitieX, Kid, Mario
bsp: gasoline_3teams_02
title: Gasoline Powered
description: Retextured and glowy with 3 teams
author: FruitieX, Kid, Mario, Freddy
bsp: gasoline_4teams_02
title: Gasoline Powered
description: Retextured and glowy with 4 teams
author: FruitieX, Kid, Mario
bsp: gasoline_noteams_02
title: Gasoline Powered - Teamless
description: Retextured and glowy
author: FruitieX, Kid, Mario
shasum: 099b0cc16fe998e5e29893dbecd5673683a5b69d
date: 2015-10-17
size: 14MB
dl: http://dl.xonotic.co/gasoline_02.pk3
pk3: dance.pk3
bsp: dance
title: <TITLE>
description: <DESCRIPTION>
author: <AUTHOR>
shasum: ef00d43838430b2d1673f03bbe1440eef100ece6
date: 2008-03-16
size: 7MB
dl: http://dl.xonotic.co/dance.pk3
Total packages found: 3
Show Map Package Details¶
simple:
xmm show dance.pk3
dance.pk3
dance
http://dl.xonotic.co/dance.pk3
detailed:
xmm show dance.pk3 -l
pk3: dance.pk3
bsp: dance
title: <TITLE>
description: <DESCRIPTION>
author: <AUTHOR>
shasum: ef00d43838430b2d1673f03bbe1440eef100ece6
date: 2008-03-16
size: 7MB
dl: http://dl.xonotic.co/dance.pk3
Export¶
You can export local maps from your library, or maps from a repository in different formats:
usage: xmm export [-h] [--format {json,shasums}] {local,repos} [filename]
positional arguments:
{local,repos} what context to export?
filename filename to export to
optional arguments:
-h, --help show this help message and exit
--format {json,shasums}, -f {json,shasums}
For example, export a maplist to a map-repo-friendly json format:
% xmm export local test.json -f json
% cat test.json
[{"mapinfo": ["maps/dance.mapinfo"], "date": 1205715512, "title": "<TITLE>", "radar": [], "waypoints": [], "gametypes": ["ctf", "dm", "lms", "arena"], "mapshot": ["maps/dance.jpg"], "description": "<DESCRIPTION>", "shasum": "ef00d43838430b2d1673f03bbe1440eef100ece6", "filesize": 7468410, "pk3": "dance.pk3", "map": ["maps/dance.map"], "author": "<AUTHOR>", "license": false, "bsp": {"dance": {"entities": {"item_cells": 14, "item_bullets": 14, "info_player_team1": 10, "item_rockets": 16, "info_player_team2": 11, "item_invincible": 1, "weapon_hagar": 2, "item_flag_team1": 1, "weapon_electro": 2, "item_health_medium": 14, "item_health_small": 20, "weapon_machinegun": 2, "item_strength": 1, "weapon_vortex": 3, "item_armor_small": 19, "weapon_devastator": 2, "item_flag_team2": 1, "weapon_grenadelauncher": 2}}}}]%
Or a list of pk3s and their respective shasums:
xmm export repos -f shasums
tail all-repos-maps.json.shasums
d88957aeff231471453f41e8ab2dad326b1875b2 acrossanocean12.pk3
e3059ee1979985151fade8b0d317422dc71ec9bb cloisterctf_vehicles.pk3
3f15789118762f469c9179f8f799747dced948cb dastower_vehicles.pk3
5af57ca19b69560cd9b00f67cbbb7ee4526bc8ac duster_mod_01.pk3
e06724125a3438a23bad4f0d3ec3b6a5ce89666a greatwall_remix_vehicles.pk3
abc9e153c37784563e4e3c2669cc88af05649399 ons-reborn_vehicles.pk3
Update¶
Get the latest list of maps from the repository:
xmm update
Updating sources json.
...100%, 7 MB, 2559 KB/s, 3 seconds passed. Done.
Advanced Usage¶
Multi-server support¶
xmm can facilitate the management of multiple servers with a ~/.xmm/servers.json
file to configure their settings, example below:
{
"myserver1": {
"target_dir": "~/.xonotic/myserver1/data/",
"library": "~/.xmm/myserver1/library.json",
"sources": "~/.xmm/sources.json"
},
"myserver2": {
"target_dir": "~/.xonotic/myserver2/data/",
"library": "~/.xmm/myserver2/library.json",
"sources": "~/.xmm/myserver2/sources.json"
}
}
An example is available in ./config/example.servers.json
To use these servers, use the -S
flag to target the server:
xmm -S myserver1 install dance.pk3
xmm -S myserver1 list
xmm -S myserver1 remove dance.pk3
Multi-repository support¶
xmm can use multiple repositories, edit the ~/.xmm/sources.json
file to configure them, example below:
{
"default": {
"download_url": "http://dl.xonotic.co/",
"api_data_file": "~/.xmm/maps.json",
"api_data_url": "http://xonotic.co/resources/data/maps.json"
}
}
An example is available in ./config/example.sources.json
To use these servers, use the -R
flag to target the server:
xmm -R myrepo install dance.pk3
xmm -R myrepo list
xmm -R myrepo remove dance.pk3
Targeting Directories¶
Sometimes you may want to install a package to an arbitrary directory:
xmm -T /path/to/directory/ install dance.pk3
Note
This install will not be tracked in the library.
Upgrading¶
0.7.0 -> 0.8.0¶
Configuration Updates¶
xmm.cfg -> xmm.ini¶
Renamed section:
[default]
to[xmm]
Renamed keys:
map_dir
->target_dir
repo_url
->download_url
api_data
->api_data_file
servers
->servers_config
New keys:
servers_config
with default~/.xmm/servers.json
servers.json¶
The package_db
key has been dropped, library
and sources
have been added.
Pickle is no longer used for serialization, data is now stored as JSON:
{
"myserver1": {
"target_dir": "~/.xonotic/myserver1/data/",
"library": "~/.xmm/myserver1/library.json",
"sources": "~/.xmm/sources.json"
},
"myserver2": {
"target_dir": "~/.xonotic/myserver2/data/",
"library": "~/.xmm/myserver2/library.json",
"sources": "~/.xmm/myserver2/sources.json"
}
}
sources.json [NEW]¶
This is a new feature that enables support for more than one repository:
{
"default": {
"download_url": "http://dl.xonotic.co/",
"api_data_file": "~/.xmm/maps.json",
"api_data_url": "http://xonotic.co/resources/data/maps.json"
}
}
For more information please see the Configuration page.
xmm.logging.ini [NEW]¶
Logging is now configurable through ~/.xmm/xmm.logging.ini
.
For more information please see the Configuration page.
Developers¶
JSON structure¶
Same structure used by xonotic-map-repository:
{
"data": [
{
"date": 1453749340,
"filesize": 7856907,
"bsp": {
"vapor_alpha_2": {
"radar": "gfx/vapor_alpha_2_mini.tga",
"waypoints": "",
"title": "Vapor",
"description": "Such CTF. Many Vehicles. Wow.",
"map": "maps/vapor_alpha_2.map",
"entities": {
"info_player_deathmatch": 4,
"info_player_team1": 11,
"info_player_team2": 11,
"item_armor_big": 10,
"item_armor_large": 4,
"item_armor_medium": 16,
"item_armor_small": 124,
"item_bullets": 10,
"item_cells": 14,
"item_flag_team1": 1,
"item_flag_team2": 1,
"item_health_large": 6,
"item_health_medium": 30,
"item_health_mega": 2,
"item_health_small": 100,
"item_invincible": 1,
"item_rockets": 20,
"item_strength": 1,
"weapon_crylink": 4,
"weapon_devastator": 6,
"weapon_electro": 2,
"weapon_grenadelauncher": 6,
"weapon_hagar": 4,
"weapon_machinegun": 6,
"weapon_vortex": 4
},
"mapinfo": "maps/vapor_alpha_2.mapinfo",
"author": "-z-",
"gametypes": [
"ctf",
"DM"
],
"license": true,
"mapshot": "maps/vapor_alpha_2.jpg"
}
},
"shasum": "3df0143516f72269f465070373f165c8787964d5",
"pk3": "map-vapor_alpha_2.pk3"
}
]
}
Plugin System¶
Checkout the examples in the ./xmmc/plugins
directory.
from xmm.plugins import pluginbase
from xmm.util import zcolors
from xmm.util import cprint
config = pluginbase.get_config()
def get_args():
command='hello'
command_help={'help': 'hello is an example plugin'}
args=['-f', '--foo']
kwargs={'type': int, 'nargs': '?', 'help': 'this is a help line'}
return command, command_help, args, kwargs
def run():
print("Hello from a plugin!")
cprint("I share the xmm util module", style='INFO')
print("{}Look, I have access to the config: {}".format(zcolors.SUCCESS, config['api_data']))
Warning
This plugin system needs to be revisited and will likely change by the next minor release.
Debugging¶
The default logging configuration comes with two file handlers, info and debug, which info enabled by default.
To enable debug, in ~/.xmm/xmm.logging.ini change:
[logger_root]
level = NOTSET
handlers = stream, info
[handlers]
keys = stream, info
To:
[logger_root]
level = NOTSET
handlers = stream, debug
[handlers]
keys = stream, debug
API¶
Server¶
-
class
xmm.server.
LocalServer
(server_name='default', source_name=None, make_dirs=False)¶ This class sets up the LocalServer object
During instantiation, new objects are created based on configuration.
The hierarchy of these objects looks like:
LocalServer
Library
Store
MapPackage
Bsp
Collection
Repository
Parameters: - server_name (
str
) – Used to reference the server by name - source_name (
str
) – If specified, the server will be associated with this one source - make_dirs (
bool
) – If directories aren’t found that are required by xmm on server init, optionally create them
Returns object: LocalServer
Commands are available offself.library
.Example: >>> from xmm.server import LocalServer >>> server = LocalServer(server_name='myserver1') >>> print(server)
-
to_json
()¶ Returns: A JSON encoded version of this object
Library¶
-
class
xmm.library.
Library
(repositories, store, map_dir)¶ A Library is a collection of MapPackage objects and commands for managing maps in the Library
Parameters: - repositories (
Collection
) – A Collection object with Repository objects - store (
Store
) – A Store object for communicate with the data store for this Library - map_dir (
str
) – The directory this Library is associated with
Returns object: Library
-
add_map_package
(package)¶ Adds a MapPackage object to
self.maps
Parameters: package ( MapPackage
) – A MapPackage object for the Library
-
discover_maps
(add=False, repository_name=None, detail=None)¶ Searches the Server‘s map_dir for map packages known by the Repository
Parameters: - add (
bool
) – Whether to add the discovered maps or not - repository_name (
str
) – A name of a repository in the repository Collection - detail (
str
) – How much detail to show, [short, None, long] - highlight (
bool
) – Whether to highlight the results
>>> from xmm.server import LocalServer >>> server = LocalServer() >>> server.library.discover_maps(add=False)
- add (
-
export_hash_index
(filename=None)¶ Parameters: filename ( str
) – Name for the exported json file, defaultmaps.json.shasums
Returns: False if fails >>> from xmm.server import LocalServer >>> # Setup the store automatically with an instance of *LocalServer* >>> server = LocalServer() >>> server.library.export_hash_index(filename='test.maps.shasums')
-
export_map_packages
(filename=None)¶ Exports all MapPackage objects from the Library Store
Parameters: filename ( str
) – Name for the exported json file, defaultxmm-export.json
Returns: False if fails >>> from xmm.server import LocalServer >>> # Setup the store automatically with an instance of *LocalServer* >>> server = LocalServer() >>> server.library.export_packages(filename='test.maps.json')
-
export_maplist
(filename=None)¶ Parameters: filename ( str
) – Name for the exported text file, defaultxmm-export.maps.txt
Returns: False if fails >>> from xmm.server import LocalServer >>> # Setup the store automatically with an instance of *LocalServer* >>> server = LocalServer() >>> server.library.export_hash_index(filename='test.maps.txt')
-
get_repository_sources
(server_name)¶ Gets the Collection from the Library of the specified LocalServer from
self.repositories
as cache, or from thesources.json
targeted byservers.json
if it is not already set.Parameters: server_name ( str
) – Server nameReturns: Collection
-
install_map
(pk3_name, repository_name=None, overwrite=False, add_to_store=True)¶ Install a MapPackage from a Repository
Parameters: - pk3_name (
str
) – A pk3 name such asvinegar_v3.pk3
, to install from the repository.’ Optionally prefixed with a URL to install map not in the repository. URL-only maps will not include rich metadata available to maps installed via the repo. - repository_name (
str
) – A name of a repository in the repository Collection - overwrite (
bool
) – Whether to overwrite the file on the file system - add_to_store (
bool
) – Whether to add the map to the store (tracked)
>>> from xmm.server import LocalServer >>> server = LocalServer(server_name='myserver1') >>> server.library.install_map(pk3_name='vinegar_v3.pk3') >>> print(server.library.maps)
- pk3_name (
-
list_installed
(detail=None)¶ List maps currently tracked by the Library
Parameters: detail ( str
) – How much detail to show, [short, None, long]Returns: int
total count>>> from xmm.server import LocalServer >>> server = LocalServer() >>> server.library.list_installed()
-
remove_map
(pk3_name)¶ Removes a map from the Library and the package from the file system
Parameters: pk3_name ( str
) – The name of a pk3, such asvinegar_v3.pk3
>>> from xmm.server import LocalServer >>> server = LocalServer(server_name='myserver1') >>> server.library.install_map_package(pk3_name='vinegar_v3.pk3') >>> print(server.library.maps) >>> server.library.remove_map(pk3_name='vinegar_v3.pk3') >>> print(server.library.maps)
-
show_map
(pk3_name, detail=None, highlight=False)¶ Convenience function to use the show_map_details helper
Parameters: - pk3_name (
str
) – The name of a pk3, such asvinegar_v3.pk3
- detail (
str
) – How much detail to show, [short, None, long] - highlight (
bool
) – Whether to highlight the results
Returns: MapPackage
>>> from xmm.server import LocalServer >>> server = LocalServer() >>> server.library.show_map('vinegar_v3.pk3', detail='long')
- pk3_name (
-
to_json
()¶ Returns: A JSON encoded version of this object
- repositories (
Repository¶
-
class
xmm.repository.
Collection
¶ A Collection is a collection of Repository objects
Returns object: Collection >>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.add_repository(repository)
-
add_repository
(repository)¶ Add a Repository to the Collection
Parameters: repository ( Repository
) –>>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.add_repository(repository) >>> print(repositories.get_repository('default'))
-
export_all_hash_index
(filename=None)¶ Parameters: filename ( str
) – Name for the exported json file, defaultall-repos-maps.json.shasums
Returns: False if fails >>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.export_all_hash_index()
-
export_all_packages
(filename=None)¶ Parameters: filename ( str
) – Name for the exported json file, defaultmaps.json
Returns: False if fails >>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.export_all_packages()
-
get_repository
(repository_name)¶ Parameters: repository_name ( str
) –Returns: A Repository object or false if name not found >>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.add_repository(repository) >>> print(repositories.get_repository('default'))
-
list_repositories
()¶ Prints a list of servers
-
search_all
(bsp_name=False, gametype=False, author=False, title=False, pk3_name=False, shasum=False, detail=None, highlight=False)¶ Searches all Repository objects in the Collection for maps matching criteria
Parameters: - bsp_name (
str
) – Search by bsp name - gametype (
str
) – Search by gametype - author (
str
) – Search by author - title (
str
) – Search by title - pk3_name (
str
) – Search by pk3_name - shasum (
str
) – Search by shasum - detail (
str
) – How much detail in the results, [short, None, long] - highlight (
bool
) – Whether to highlight the search string
>>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.add_repository(repository) >>> print(repositories.search_all(bsp_name='vinegar_v3'))
- bsp_name (
-
to_json
()¶ Returns: A JSON encoded version of this object
-
update_all
()¶ Update the data for all Repository objects in the Collection
>>> from xmm.repository import Collection >>> from xmm.repository import Repository >>> repositories = Collection() >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repositories.update_all()
-
-
class
xmm.repository.
Repository
(name, download_url, api_data_url, api_data_file)¶ A Repository contains a url which hosts content matching the JSON format described in the documentation
Parameters: - name (
str
) – A name for this Repository - download_url (
str
) – The url where the pk3 files should be downloaded from - api_data_url (
str
) – URL serving maps in the JSON format described in the documentation - api_data_file (
str
) – Local cache fo the repo data.
Returns object: Repository
>>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json')
-
export_hash_index
(filename=None)¶ Parameters: filename ( str
) – Name for the exported json file, defaultmaps.json.shasums
Returns: False if fails >>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repository.export_hash_index('test.shasums')
-
export_packages
(filename=None)¶ Parameters: filename ( str
) – Name for the exported json file, defaultmaps.json
Returns: False if fails >>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repository.export_packages('test.json')
-
get_hash_index
()¶ Gets a list of all pk3s and their shasums
Returns: False if fails >>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> print(repository.get_hash_index())
-
get_packages
()¶ Gets the cached map list from Repository or reads from file if cache not available
Returns: json
>>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> print(repository.get_packages())
-
search_maps
(bsp_name=False, gametype=False, author=False, title=False, pk3_name=False, shasum=False, detail=None, highlight=False)¶ Searches the repository for maps matching criteria
Parameters: - bsp_name (
str
) – Search by bsp name - gametype (
str
) – Search by gametype - author (
str
) – Search by author - title (
str
) – Search by title - pk3_name (
str
) – Search by pk3_name - shasum (
str
) – Search by shasum - detail (
str
) – How much detail in the results, [short, None, long] - highlight (
bool
) – Whether to highlight the search string
>>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repository.search_maps(bsp_name='dance' gametype='ctf')
- bsp_name (
-
show_map
(pk3_name, detail=None, highlight=False)¶ Convenience function to use the show_map_details helper
Parameters: - pk3_name (
str
) – The name of a pk3, such asvinegar_v3.pk3
- detail (
str
) – How much detail to show, [short, None, long] - highlight (
bool
) – Whether to highlight the results
Returns: MapPackage
>>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repository.show_map(pk3_name='vinegar_v3.pk3')
- pk3_name (
-
to_json
()¶ Returns: A JSON encoded version of this object
-
update_repo_data
()¶ Updates sources cache with latest maps from Repository
>>> from xmm.repository import Repository >>> repository = Repository(name='default', download_url='http://dl.repo.url/', >>> api_data_url='http://api.repo.url/maps.json', api_data_file='~/.xmm/maps.json') >>> repository.update_repo_data()
- name (
Map Packages¶
-
class
xmm.map.
Bsp
(pk3_file='', bsp_name='', bsp_file='', map_file='', mapshot='', radar='', title='', description='', mapinfo='', author='', gametypes=None, entities=None, waypoints='', license=False)¶ A Bsp is a child of a MapPackage that holds metadata about this map
Parameters: - pk3_file (
str
) – The pk3_file name of the package this bsp is in - bsp_name (
str
) – The bsp_name of the bsp_file - bsp_file (
str
) – The bsp_file - map_file (
str
) – The map_file for the bsp_file if it exists - mapshot (
str
) – The mapshot for the bsp_file if it exists - title (
str
) – The title for the bsp_file if it exists - description (
str
) – The description for the bsp_file if it exists - mapinfo (
str
) – The mapinfo for the bsp_file if it exists - author (
str
) – The author for the bsp_file if it exists - gametypes (
list
) – The gametypes for the bsp_file if it exists - entities (
str
) – The entities for the bsp_file if they exists - waypoints (
str
) – The waypoints for the bsp_file if it exists - license (
str
) – The license for the bsp_file if it exists
Returns object: Bsp
-
to_json
()¶ Returns: A JSON encoded version of this object
- pk3_file (
-
class
xmm.map.
MapPackage
(map_package_json)¶ MapPackage contains top-level metadata about a pk3 file and list of Bsp objects inside this package
Parameters: map_package_json ( string|dict
) –A dict or JSON string that matches “specification” in the Developers section of the documentation.
See basic example below:
{ "data": [ { "date": 1453749340, "filesize": 7856907, "bsp": { "vapor_alpha_2": { "radar": "gfx/vapor_alpha_2_mini.tga", "waypoints": "", "title": "Vapor", "description": "Such CTF. Many Vehicles. Wow.", "map": "maps/vapor_alpha_2.map", "entities": { "info_player_deathmatch": 4, "info_player_team1": 11, "info_player_team2": 11, "item_armor_big": 10, "item_armor_large": 4, "item_armor_medium": 16, "item_armor_small": 124, "item_bullets": 10, "item_cells": 14, "item_flag_team1": 1, "item_flag_team2": 1, "item_health_large": 6, "item_health_medium": 30, "item_health_mega": 2, "item_health_small": 100, "item_invincible": 1, "item_rockets": 20, "item_strength": 1, "weapon_crylink": 4, "weapon_devastator": 6, "weapon_electro": 2, "weapon_grenadelauncher": 6, "weapon_hagar": 4, "weapon_machinegun": 6, "weapon_vortex": 4 }, "mapinfo": "maps/vapor_alpha_2.mapinfo", "author": "-z-", "gametypes": [ "ctf", "DM" ], "license": true, "mapshot": "maps/vapor_alpha_2.jpg" } }, "shasum": "3df0143516f72269f465070373f165c8787964d5", "pk3": "map-vapor_alpha_2.pk3" } ] }
Returns object: MapPackage
>>> from xmm.map import MapPackage >>> with open('my_map.json') as f: >>> data = f.read() >>> my_map = MapPackage(map_package_json=data)
-
show_map_details
(detail=None, search_string='', highlight=False)¶ Helper function for pretty printing details about a MapPackage
Convenience function to use the show_map_details helper
Parameters: - detail (
str
) – How much detail to show, [short, None, long] - search_string (
str
) – A string to highlight withhighlight=True
- highlight (
bool
) – Whether to highlight the results
Returns: MapPackage
- detail (
-
to_json
()¶ Returns: A JSON encoded version of this object
-
Store¶
-
class
xmm.store.
Store
(package_store_file)¶ Store is for interacting with the datastore for a Library
Parameters: package_store_file ( str
) – The file where the data is stored>>> import os >>> from xmm.store import Store >>> package_store_file = os.path.expanduser('~/.xmm/library.json') >>> store = Store(package_store_file=package_store_file)
Returns object: Store
-
add_package
(package)¶ Adds a MapPackage to the Library Store
Parameters: package ( MapPackage
) – MapPackage to add>>> import os >>> from xmm.map import MapPackage >>> from xmm.store import Store >>> package_store_file = os.path.expanduser('~/.xmm/library.json') >>> with open('my_map.json') as f: >>> data = f.read() >>> my_map = MapPackage(map_package_json=data) >>> store = Store(package_store_file=package_store_file) >>> store.add_package(my_map)
Returns: False if fails
-
export_packages
(filename=None)¶ Exports all MapPackage objects from the Library Store
Parameters: filename ( str
) – Name for the exported json file, defaultxmm-export.json
Returns: False if fails >>> from xmm.server import LocalServer >>> # Setup the store automatically with an instance of *LocalServer* >>> server = LocalServer() >>> server.library.store.export_packages(filename='test.json')
-
get_package_db
()¶ Searches the repository for maps matching criteria
>>> import os >>> from xmm.store import Store >>> package_store_file = os.path.expanduser('~/.xmm/library.json') >>> store = Store(package_store_file=package_store_file) >>> store.get_package_db()
Returns: dict
-
remove_package
(package)¶ Removes a MapPackage to the Library Store
Parameters: package ( MapPackage
) – MapPackage to remove>>> import os >>> from xmm.map import MapPackage >>> from xmm.store import Store >>> package_store_file = os.path.expanduser('~/.xmm/library.json') >>> with open('my_map.json') as f: >>> data = f.read() >>> my_map = MapPackage(map_package_json=data) >>> store = Store(package_store_file=package_store_file) >>> store.remove_package(my_map)
Returns: False if fails
-
to_json
()¶ Returns: A JSON encoded version of this object
-
Utility¶
-
class
xmm.util.
ObjectEncoder
(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)¶ JSONEncoder subclass that leverages an object’s __json__() method, if available, to obtain its default JSON representation.
-
xmm.util.
check_if_not_create
(file, template)¶ Checks for a file, if it doesn’t exist, it will be created from a template.
Parameters: - file (
str
) – filename with path to file - template (
str
) – filename with path to template file
- file (
-
xmm.util.
convert_size
(number)¶ Convert and integer to a human-readable B/KB/MB/GB/TB string.
Parameters: number ( int
) – integer to be converted to readable stringReturns: str
-
xmm.util.
cprint
(string, style='INFO')¶ Terminal formatting convenience function.
Parameters: - string (
str
) – A string to print. - style (
str
) –A style to print.
Options:
- HEADER
- INFO
- SUCCESS
- WARNING
- FAIL
- ENDC (end color)
- BOLD
- UNDERLINE
>>> cprint("Success", style='SUCCESS')
- string (
-
xmm.util.
create_if_not_exists
(file, contents)¶ Checks for a file, if it doesn’t exist, it will be created from a template.
Parameters: - file (
str
) – filename with path to file - contents (
str
) – string contents of the file being created
- file (
-
xmm.util.
download_file
(filename_with_path, url, use_curl=False, overwrite=False)¶ downloads a file from any URL
Parameters: - filename_with_path (
str
) – filename with path to download file to - url (
str
) – URL to download map from - use_curl (
bool
) – Whether or not to use curl to download the file, defaultFalse
- overwrite – Whether or not to overwrite the existing file, default
False
- filename_with_path (
-
xmm.util.
file_is_empty
(filename)¶ Checks to see if a file is empty
Parameters: filename ( str
) – string filenameReturns: bool
-
xmm.util.
hash_file
(filename)¶ Returns the SHA-1 hash of the file passed into it
Parameters: filename ( str
) – string filenameReturns: str
-
xmm.util.
parse_config
(config_file)¶ downloads a file from any URL
Parameters: config_file ( str
) – filename with path to config fileReturns: dict
-
xmm.util.
query_yes_no
(question, default='yes')¶ Ask a yes/no question via raw_input() and return their answer.
Parameters: - question (
str
) – a string that is presented to the user. - default (
str
) – is the presumed answer if the user just hits <Enter>. It must be “yes” (the default), “no” or None (meaning an answer is required of the user).
The “answer” return value is True for “yes” or False for “no”.
- question (
-
xmm.util.
replace_last
(string, old, new)¶ Replace the last occurrence of a pattern in a string
Parameters: - string (
str
) – string - old (
str
) – string to find - new (
str
) – string to replace
Returns: str
- string (
-
xmm.util.
reporthook
(count, block_size, total_size)¶ Pretty progress for urllib downloads.
>>> import urllib.request >>> urllib.request.urlretrieve(url, filename, reporthook)
https://github.com/yahoo/caffe/blob/master/scripts/download_model_binary.py
-
class
xmm.util.
zcolors
¶ Terminal formatting.
Options:
- HEADER
- INFO
- SUCCESS
- WARNING
- FAIL
- ENDC (end color)
- BOLD
- UNDERLINE
>>> "{}eggs{}: {}spam{}".format(zcolors.INFO, zcolors.ENDC, zcolors.UNDERLINE, zcolors.ENDC)
Exceptions¶
-
exception
xmm.exceptions.
HashMismatchError
¶ Raise when a file hash mismatches
-
exception
xmm.exceptions.
PackageLookupError
¶ Raise when Package does not exist in Repository
-
exception
xmm.exceptions.
PackageMetadataWarning
¶ Raise when Package installs from a URL and has no metadata associated with it.
-
exception
xmm.exceptions.
PackageNotTrackedWarning
¶ Raise when Package is not tracked in the local db
-
exception
xmm.exceptions.
RepositoryLookupError
¶ Raise when Repository lookup fails
-
exception
xmm.exceptions.
RepositoryUpdateError
(reason, filename=None)¶ Raise when Repository update fails
-
exception
xmm.exceptions.
ServerLookupError
¶ Raise when Server lookup fails
Tests¶
Unit tests can be run with py.test
and coverage tests with tox
:
make tests
make tests-coverage
make lint
make clean