Modules¶
Command¶
- class Command(argv)¶
Parse command line call, for easy access to parameters.
Warning
This class does not work, on purpose. Correctly parsing command line depends on each command, and implementing it correctly would mean re-implementing the parsing process used by every binary that is to be wrapped with CLAchievements. This is not going to happen. What is done is:
Any argument not starting with
-
is a positional argument.Any argument starting with a single
-
is a list of short options (-foo
is equivalent to-f -o -o
). Those options do not have any arguments.Any argument starting with double
--
is a long option. If it contains a=
, it is intepreted as an option with its argument; otherwise, it does not have any arguments.
The available attributes are:
- bin¶
Base name of the wrapped binary (more or less equivalent to
os.path.basename(sys.argv[0])
).
- short¶
multidict.MultiDict
of short command line arguments (that is, arguments starting with a single-
). Keys are the arguments, and values are the options to the arguments. See the warning at the beginning of the documentation of this class.
- long¶
multidict.MultiDict
of long command line arguments (that is, arguments starting with a double-
). Keys are the arguments, and values are the options to the arguments. See the warning at the beginning of the documentation of this class.
- positional¶
List of positional arguments (that is, arguments not starting with -).
The following doctest serves as an example.
>>> command = Command("/usr/bin/foo tagada -bar --baz --baz=plop tsoin tsoin".split()) >>> command.bin 'foo' >>> command.short <MultiDict('b': None, 'a': None, 'r': None)> >>> command.long <MultiDict('baz': None, 'baz': 'plop')> >>> command.argv ['/usr/bin/foo', 'tagada', '-bar', '--baz', '--baz=plop', 'tsoin', 'tsoin'] >>> command.positional ['tagada', 'tsoin', 'tsoin']
Achievements¶
- class Achievement(command, database)¶
Achievement: Something that is unlocked when user perform the right commands.
A how-to is available in the Write your own achievement section, which illustrates this class documentation.
This class is a context manager. The
__enter__()
method is called before the actual wrapped command call, and the__exit__()
method is called after it. One of those method must callunlock()
when the conditions to fulfill the achievement are met.- _description = None¶
Description of the achievement. If None, the first non-empty line of the class docstring is used instead.
- bin = None¶
List of binaries loading this achievement. If None, this achievement is always loaded.
- first()¶
This method is called once: when this achievement is loaded for the first time.
This method is meant to be subclassed.
- icon = 'star.svg'¶
File name of the icon (relative to the data directory).
- last()¶
This method is called once: when this achievement has just been unlocked.
This method is meant to be subclassed.
- title = None¶
Title of the achievement. If None, the class is an abstract achievement, to be subclassed.
- unlock()¶
Called when achievement is unlocked.
Mark this achievement as unlocked in the database.
Notify user.
This method is to be called by one of the
__enter__()
or__exit__()
method when the conditions to unlock the achievement are fulfilled.
- class SimplePersistentDataAchievement(command, database)¶
Achievement, with a simple way to store data into a database.
It is very simple to use, since accessing or writing to
self.data
will automatically read or write data from the database.But the cost is that concurrent access to the database will lead to errors. For instance, on a test, running fifty concurrent calls to
self.data += 1
only incrementedself.data
by about twenty values.This is wrong but:
this is just a game, so there is no important consequence to this error;
this is a very simple class. If you want a more robust one, please provide a patch.
- property data¶
Picklable
persistent data, specific to this achievement.Note
Database is not locked when reading or writing this data. That is, concurrent runs of
self.data += 1
are not guaranteed to succeed.Note
Be careful to call
self.data = MY_NEW_DATA
to store your updated data. This means that, ifself.data
is a dictionary,self.data.update({"foo": "bar"})
will not store anything.
- default_data = None¶
Data stored as this achievement persistent data when this achievement is met for the first time.
Test utils¶
- test_lock(func)¶
Decorator for test methods keeping the achievement locked.
To be applied to methods of
Achievement
.Those methods must iterate over shell commands (as strings). Executing those commands must not unlock the achievement. Otherwise, the corresponding test will fail.
- test_unlock(func)¶
Decorator for test methods unlocking the achievement.
To be applied to methods of
Achievement
.Those methods must iterate over shell commands (as strings). Executing those commands must unlock the achievement. Otherwise, the corresponding test will fail.