Pychievements, the Python Achievements Framework!¶
Pychievements is a framework for creating and tracking achievements within a Python application. It includes functions specifically for creating commandline applications, though it is flexible enough to be used for any application such as web applications.
See the examples to get a good feel for what Pychievements offers. Source can be found on github.
Getting Started¶
Getting Started will guide you through creating your first achievements an introducing you to the pieces of the system. From there, visit the Reference for in-depth information.
Installing Pychievements¶
- Pychievements can be installed with
pip
: $ pip install pychievements
Introduction to Pychievments¶
Pychievements has a number of modules that you’ll need to be at least familiar with:
- tracker
- The default achievement tracker for pychievements is instantiated at import and is used to track all registered achievements for specific tracked_ids.
- Achievement
- Base Achievment class.
- icons.Icon
- Base Icon class. Icons are used to know what to display for a given goal within an achievement and have two states, achieved and unachieved.
- backends.AchievementBackend
- Pychievements have pluggable backends for storing tracked achievement data. The default
AchievementBackend
simply keeps everyting in memory, meaning it will be lost when the application is closed. The backend the tracker is using can be updated with theset_backend
method.- signals
- You can register functions as callbacks that can recieve Pychievement signals. Signals can be generated when a level is changed, when a new goal is reached, or when all goals have been achieved for a given achievement.
Achievements¶
At the core of Pychievements is the Achievement
class. It is used to define goals that are
obtained at specified levels. Levels are simply an integer. At a minimum, achievements must have
the following attributes defined:
- name : Display name of your achievement
- category : Defaults to “achievements”
- goals : A tuple of goals. A goal is a dictionary with the following keys: [“level”, “name”, “icon”, “description”]
An example Achievement class:
class MyAchievement(Achievement):
name = "My Achievement"
category = "achievements"
keywords = ("my", "achievement")
goals = (
{"level": 10, "name": "Level 1", "icon": icons.star, "description": "Level One" },
{"level": 20, "name": "Level 2", "icon": icons.star, "description": "Level Two" },
{"level": 30, "name": "Level 3", "icon": icons.star, "description": "Level Three" },
)
An achievements current level for an id can tracked with either the increment
or evaluate
functions, which the achievment can override to provide custom level manipulation.
The Tracker¶
A singleton tracker
is created on import that is available as pychievements.tracker
. The
tracker provides an interface for interacting with registered achievements for a given
tracked_id
. The tracker lets you:
- increment level of an achievement for a tracked_id
- evaluate level of an achievement for a tracked_id
- query all achievements by category or keywords
- query all achieved goals of an achievement for a tracked_id
- query all unachieved goals of an achievement for a tracked_id
- query the current goal being worked towards of an achievement for a tracked_id
The tracker works with the configured backend to store and retrieve all of the tracked levels.
Icons¶
Icons are simple classes that provide the “icon” (or what is displayed) for an achievment goal. It
must define what to display for when the goal has been achieved (achieved
) or not
(unachieved
)
Examples¶
The easiest way to get started to check out the examples in the examples folder in the the repository. Then check out the Reference for more information.
Reference¶
Achievements¶
-
class
pychievements.achievements.
Achievement
(current=0)[source]¶ Base Achievement class.
An achievement primarily consists of ‘goals’, being levels that can be reached. Instances of Achievements are used to track progress, and the current level for individual IDs. For this, an Achievement implements a number of functions to interact with the current level. Achievements can also have a
category
(string) andkeywords
(tuple of strings) that can be used to filter Achievements.Goals are defined as a tuple of tuples with the format:
goals = ( {'level': 10, 'name': 'Level 1', 'icon': icons.star, 'description': 'Level One'}, {'level': 20, 'name': 'Level 2', 'icon': icons.star, 'description': 'Level Two'}, {'level': 30, 'name': 'Level 3', 'icon': icons.star, 'description': 'Level Three'}, )
Arguments:
- level
- A positive integer that must be reached (greater than or equal) to be considered ‘met’
- name
- A short name for the level
- icon
- The
Icon
to represent the level before it has been achieved. This must be anpychievements.icons.Icon
class.
Note
There are simple ASCII icons available from
pychievements.icons
- description
- A longer description of the level.
Achievements can be updated in two ways:
increment
andevaluate
. Increment increments the current level given an optional set of arguments, where evaluate performs a custom evaluation a sets the current level based on that evaluation.Increment is best used when the application is aware of achievement tracking, and calls to increment can be placed throughout the application.
Evaluate is best used when actions may happen externally, and cannot be tracked using repeated calls to increment. Evaluate will also return the list of achieved goals after it has performed its evaluation.
An Achievement can be initialized with a
current
level, for example when restoring for a saved state.-
achieved
¶ Returns a list of achieved goals
-
current
¶ Returns the current level being achieved (meaning haven’t achieved yet) as a tuple:
- ::
- (current_level, (required_level, name, icon, description))
If all achievements have been achieved, the current level is returned with a None:
- ::
- (current_level, None)
-
evaluate
(*args, **kwargs)[source]¶ Performs a custom evaluation to set the current level of an achievement. Returns a list of achieved goals after the level is determined.
-
increment
(amount=1, *args, **kwargs)[source]¶ Increases the current level. Achievements can redefine this function to take options to increase the level based on given arguments. By default, this will simply increment the current count by
amount
(which defaults to 1).
-
unachieved
¶ Returns a list of goals that have not been met yet
Icons¶
pychievments.icons includes the Icon
class as well as a number of pre-defined icons useful
for CLI applications.
- unicodeCheck
- unicdeCheckBox
- star
-
class
pychievements.icons.
Icon
(unachieved='', achieved='')[source]¶ Simple class to represent an
Icon
for an achievement. It provides to functions,achieved
, andunachieved
, which will return the displayable icon for the appropriate state.The base Icon class can be used without modification to create simple text Icons, e.g.:
star = Icon(unachieved=' No ', achieved=' Yes ')
Trackers¶
-
class
pychievements.trackers.
AchievementTracker
(backend=None)[source]¶ AchievementTracker tracks achievements and current levels for
tracked_id
using a configured achievement backend.A default instance of Achievement tracker is created as a singleton when pycheivements is imported as
pychievements.tracker
. Most often, this is what you will want to use.Arguments:
- backend:
- The backend to use for storing/retrieving achievement data. If
None
, the defaultAchievementBackend
will be used, which stores all data in memory.
Note
The backend the tracker is using can be updated at any time using the
set_backend()
function.-
achieved
(tracked_id, achievement)[source]¶ Returns
achieved
for a given tracked_id. See :ref:Achievement
-
achievement_for_id
(tracked_id, achievement)[source]¶ Returns
Achievement
for a giventracked_id
. Achievement can be anAchievement
class or a string of the name of an achievement class that has been registered with this tracker.Raises NotRegistered if the given achievement is not registered with the tracker.
If
tracked_id
has not been tracked yet by this tracker, it will be created.
-
achievements
(category=None, keywords=[])[source]¶ Returns all registered achievements.
Arguments:
- category
- Filters returned achievements by category. This is a strict string match.
- keywords
- Filters returned achievements by keywords. Returned achievements will match all given keywords
-
achievements_for_id
(tracked_id, category=None, keywords=[])[source]¶ Returns all of the achievements for tracked_id that match the given category and keywords
-
current
(tracked_id, achievement)[source]¶ Returns
current
for a given tracked_id. See :ref:Achievement
-
evaluate
(tracked_id, achievement, *args, **kwargs)[source]¶ Evaluates an achievement for a given
tracked_id
. Achievement can be anAchievement
class or a string of the name of an achievement class that has been registered with this tracker.Raises NotRegistered if the given achievement is not registered with the tracker.
If
tracked_id
has not been tracked yet by this tracker, it will be created before evaluating.Returns list of achieved goals for the given achievement after evaluation
-
increment
(tracked_id, achievement, amount=1, *args, **kwargs)[source]¶ Increments an achievement for a given
tracked_id
. Achievement can be anAchievement
class or a string of the name of an achievement class that has been registered with this tracker.Raises NotRegistered if the given achievement is not registered with the tracker.
If
tracked_id
has not been tracked yet by this tracker, it will be created before incrementing.Returns an list of achieved goals if a new goal was reached, or False
-
is_registered
(achievement)[source]¶ Check if an achievement is registered with this AchievementTracker
-
register
(achievement_or_iterable, **options)[source]¶ Registers the given achievement(s) to be tracked.
-
set_level
(tracked_id, achievement, level)[source]¶ Returns
set_level
for a given tracked_id. See :ref:Achievement
Signals¶
-
class
pychievements.signals.
Signal
[source]¶ Base class for all signals
Internal attributes:
- receivers
- { receiverkey(id): receiver }
-
connect
(receiver, sender=None, dispatch_uid=None)[source]¶ Connect receiver to sender for signal.
Arguments:
- receiver
- A function or an instance method which is to recieve signals.
- sender
- The sender to which the receiver should respond. Must be None to recieve events from any sender.
- dispatch_uid
- An identifier used to uniquely identify a particular instance of a receiver. This will usually be a string, though it may be anything hashable.
-
disconnect
(receiver=None, sender=None, dispatch_uid=None)[source]¶ Disconnect receiver from sender for signal.
Arguments:
- receiver
- The registered receiver to disconnect. May be none if dispatch_uid is specified.
- sender
- The registered sender to disconnect
- dispatch_uid
- the unique identifier of the receiver to disconnect
-
send
(sender, **named)[source]¶ Send signal from sender to all connected receivers.
If any receiver raises an error, the error propagates back through send, terminating the dispatch loop, so it is quite possible to not have all receivers called if a raises an error.
Arguments:
- sender
- The sender of the signal Either a specific object or None.
- named
- Named arguments which will be passed to receivers.
Returns a list of tuple pairs [(receiver, response), ... ].
-
send_robust
(sender, **named)[source]¶ Send signal from sender to all connected receivers catching errors.
Arguments:
- sender
- The sender of the signal. Can be any python object (normally one registered with a connect if you actually want something to occur).
- named
- Named arguments which will be passed to receivers. These arguments must be a subset of the argument names defined in providing_args.
Return a list of tuple pairs [(receiver, response), ... ].
If any receiver raises an error (specifically any subclass of Exception), the error instance is returned as the result for that receiver. The traceback is always attached to the error at
__traceback__
.
-
pychievements.signals.
receiver
(signal, **kwargs)[source]¶ A decorator for connecting receivers to signals. Used by passing in the signal (or list of signals) and keyword arguments to connect:
@receiver(goal_achieved) def signal_receiver(sender, **kwargs): ... @receiver([goal_achieved, level_increased], sender=tracker) def signals_receiver(sender, **kwargs): ...
Backends¶
-
class
pychievements.backends.
AchievementBackend
[source]¶ Achievement backends implement the getting/setting/updating of achievements for
tracked_id
. Achievements in the system are tracked for a specific, unique ID,tracked_id
.AchievementBackend is the most basic implementation of an AchievementBackend, storing all tracked information in memory and never persisting it. All of the functions of an AchievementBackend work to retrieve an
Achievement
instance for a giventracked_id
, and run the appropriate function on it, storing the results. In the least, storing results for a specific achievement, for a specifictarget_id
should include thetarget_id
, theAchievement
class name (Achievement.__name__
), and the current level (Achievement.current
)Note
AchievementBackend is NOT thread safe
-
achievement_for_id
(tracked_id, achievement)[source]¶ Retrieves the current
Achievement
for the giventracked_id
. If the giventracked_id
does not exist yet, it should be created. Also, if the giventracked_id
hasn’t tracked the givenAchievement
yet, a new instance of theAchievement
should be created for the giventracked_id
-
-
class
pychievements.backends.
SQLiteAchievementBackend
(dbfile)[source]¶ Stores achievement data in a SQLite database.
Arguments:
- dbfile
- The full path and file name to store the SQLite database
To use, create the backend and then use the
set_backend()
method of the tracker.mybackend = SQLiteAchievementBackend('/some/db.file') tracker.set_backend(mybackend)
CLI¶
-
pychievements.cli.
print_goal
(goal, achieved=False, level=None, indent=2)[source]¶ Print a goals description with its icon. Achieved (True/False) will choose the correct icon from the goal. If a level is specified, a tracker line will be added under the icon showing the current level out of the required level for the goal. If level is > the required level, achieved will be set to true.
-
pychievements.cli.
print_goals
(achievement_or_iter, indent=2)[source]¶ Displays all of the available goals registered for the given achievement(s)
-
pychievements.cli.
print_goals_for_tracked
(tracked_id, achievement_or_iter=None, achieved=True, unachieved=False, only_current=False, level=False, category=None, keywords=[], indent=2, tracker=None)[source]¶ Prints goals for a specific
tracked_id
from as tracked by atracker
. By default, this will print out all achieved goals for every achievement in thetracker
.Arguments:
- achievment_or_iter
- If
None
, this will print goals for all achievements registered with thetracker
. Otherwise anAchievement
or list of achievements can be given to show goals for. - achieved
- If True, prints out goals that have allready been achieved.
- unachieved
- If True, prints out goals that have not been achieved.
- only_current
- If True, only prints the goal currently being worked on (next to be achieved). This will
override the
achieved
andunachieved
options. - category
- Category to filter achievements from the tracker.
- keywords
- Keywords to filter achievements from the tracker.
- level
- If True, show the current level with the achievements
- tracker
- The tracker to use for getting information about achievements and
tracked_id
. Iftracker
isNone
, this will default to using the default tracker.
Contribute¶
If you’d like to contribute, simply fork the repository, commit your changes to the master branch (or branch off of it), and send a pull request. Make sure you add yourself to AUTHORS.