Guided Tour of the Code¶
Typically, this is where the API documentation would go, but this isn’t a library. However, this is a nice overview for someone wanting to get into the code.
Basic Structure¶
The project is primarily structured as a python package. The following items in the root of the project are common to many python package distributions (For more info, check out this:
- docs/:
- Documentation for the project
- tests/:
- Unit tests for the project
- thekraf/:
- The main python package of the project that is installed by setuptools
- MANIFEST.in:
- setup.py is configured to search for python code to include when installing the package into site-packages. To include non-python files, one option is to reference those files with rules defined in this file.
- README.rst:
- Introductory information about the project
- requirements.txt:
- Python package dependencies for the project. Although dependencies can be defined in setup.py, this file is more capable, especially when not all requirements are hosted on PyPI (such as with this project).
- setup.cfg:
- Site-specific setup config (More info here). In this case, it is being used to configure bumpversion.
- setup.py:
- Primary configuration file for package distribution.
Core Logic¶
thekraf.diceutils¶
Utilities for use with dice
-
class
thekraf.diceutils.DiceUtils[source]¶ Bases:
objectUtilities for use with/on dice
-
VALS= (1, 2, 3, 4, 5, 6)¶
-
static
as_string(dice)[source]¶ Convert dice to string representation
Dice are sorted before conversion so this also the key for the caches
Parameters: dice (tuple[int]) – Dice to convert Returns: Corresponding string Return type: str
-
static
concat(dice, other)[source]¶ Concatenate dice
Parameters: - dice (tuple[int]) – Starting dice
- other (tuple[int]) – Dice to add on
Returns: Concatenated dice
Return type: tuple[int]
-
classmethod
create_dice(dice_repr)[source]¶ Create dice values from various representations
Representation can be:
string
- ‘123456’
- ‘1 2 3 4 5 6’
- ‘1,2,3,4,5,6’
sequence of strings
- [‘1’, ‘1’, ‘2’, ‘2’]
sequence of int (basically passthrough)
- (3, 4, 5)
Parameters: dice_repr (str) – String to parse
Returns: Corresponding values
Return type: tuple[int]
Raises: TypeError– If dice_repr can’t be converted to diceValueError– If dice values are not inVALS
-
static
diff(minuend, subtrahend)[source]¶ Return dice in minuend less the dice in the subtrahend
Parameters: - minuend (tuple[int]) – Starting dice
- subtrahend (tuple[int]) – The dice to remove from minuend
Returns: The difference
Return type: tuple[int]
-
static
is_dice_inst(obj)[source]¶ True if obj is an instance of dice
Parameters: obj (object) – Object to test Returns: Return type: bool
-
-
thekraf.diceutils.norm_dice(arg_index=0)[source]¶ Normalize any dice representations as true dice
Parameters: arg_index (int) – Index of the target arg in the parameter list. Usually this would be the first arg, but it would be the second if used on a class or instance method. Returns: Configured decorator
thekraf.game¶
The game controller logic
-
class
thekraf.game.Game(**kwargs)[source]¶ Bases:
thekraf.game.GameTurn,thekraf.db.models.BaseModelA game of thekraf
A game consists of a series of
Cycles or rounds in which eachPlayertakes aTurn.-
created¶
-
cycles¶
-
game_info()[source]¶ Format data about the game so it can easily be displayed
This is mostly for debugging purposes
Returns: Formatted data Return type: tuple[tuple[str]]
-
goal¶
-
id¶
-
is_anonymous¶
-
min_bank¶
-
min_first_bank¶
-
mode¶
-
modified¶
-
opts¶
-
query= <sqlalchemy.orm.query.Query object>¶
-
-
class
thekraf.game.GameTurn(**kwargs)[source]¶ Bases:
thekraf.gamemodels.GameGame logic specific to
Turns-
bank(dice=())[source]¶ Bank scored dice, thereby completing a turn
Parameters: dice (tuple(int) – Additional dice to include before banking
-
bankable(*args, **kwargs)¶
-
dice_to_roll_num()[source]¶ Calculate how many dice should be rolled
Returns: The number to roll Return type: int
-
roll_dice()[source]¶ Roll any unscored dice or all of them if all have been scored
Don’t check for busted immediately after roll. That way, the user can be informed of the bust. Rolling at that point will act as an acknowledgement by the user so the turn can be marked complete.
-
select_and_score(*args, **kwargs)¶
-
select_and_score_min()[source]¶ Select the best scoring min number of scorable dice from rolled
Frequently, a player may choose to re-roll scoring dice for the chance at a higher score. However, at least one set of scoring dice must be set aside before rolling what it remaining. This method determines the smallest subcombo of the rolled dice that is scorable. If there are multiple combos of the same size, the one with the highest score is returned.
-
turn_info()[source]¶ Format data about the turn so it can easily be displayed
This is mostly for debugging purposes
Returns: Formatted data Return type: tuple[tuple[str]]
-
turn_table_info()[source]¶ Format data about the turn so it is easily displayable in a table
Returns: Formatted data Return type: tuple[tuple[str]]
-
unscore(*args, **kwargs)¶
-
-
thekraf.game.displayable_info(objs, spec)[source]¶ Semi-automatic formatting of attrs for display
Spec format:
Iterable of triplets (name, title, value) where:
- name
- Name of attr on one of the objs
- title
- Display name for the attr. If None, it will become title-case of name.
- value
- Attr value. If None, objs will be searched for attr. If attr is not found, it will remain None.
Parameters: - objs (collections.Iterable[object]) – Objects to search for attrs
- spec (collections.Iterable[collections.Iterable]) – Dpecification as explained above
Returns: Pairs of title str and value
Return type: collections.Generator[tuple[str, object]]
thekraf.gamemodels¶
Models for use by the game controller
-
class
thekraf.gamemodels.Cycle(**kwargs)[source]¶ Bases:
objectA cycle or round of the game
Each player gets one turn per cycle
-
pids¶ tuple[int] – IDs of players
-
turns¶ list[Turn] – Turns in the cycle
-
complete¶ True if all players have completed their turn for this round
-
-
class
thekraf.gamemodels.Game(**kwargs)[source]¶ Bases:
objectModel for a game
-
mode¶ str – Game mode. Possible modes are:
- ‘rounds’ – The most points after a certain number of rounds
- ‘points’ – First player to reach a certain number of points
-
goal¶ int – Value associated withe the game mode to determine the end of the game
-
min_first_bank¶ int – The minimum running total of a turn required to bank the first time
-
min_bank¶ int – The minimum running total of a turn required to bank after already being on the board
-
pids¶ tuple[int] – IDs of players in the game
-
cycles¶ list[Cycle] – Rounds of the game
-
MODES= {'rounds': {'goal': 10, 'min_first_bank': 300, 'min_bank': 50}, 'points': {'goal': 10000, 'min_first_bank': 500, 'min_bank': 50}}¶
-
complete¶ bool – True if the goal of the game has been reached
-
cycle¶ Cycle – The current cycle
-
description¶
-
pids
-
player¶
-
player_names¶
-
players¶
-
score_per_turns¶ dict[int, int] – Player ID -> total for each turn
-
totals¶ dict[int, int] – Player ID -> running total for game
-
turn¶ Turn – The current turn
Returns: Return type: thekraf.gamemodels.Turn
-
turns¶ collections.Generator[Turn] – All turns of all rounds
-
-
class
thekraf.gamemodels.Player(**kwargs)[source]¶ Bases:
objectA player of a game
-
id¶ int – Unique player ID
-
name¶ str – Name of player
-
-
class
thekraf.gamemodels.Turn(**kwargs)[source]¶ Bases:
objectSeries of rolls and scores until bank or bust
Each player will have one Turn per Round. A turn consists of a series of rolls and scores. After scoring, the player may choose to continue rolling the remaining dice (or all dice if all dice have been scored), or bank the running total for the turn.
After a roll, the player must score with at least one die. If the player is unable to score with any of the dice, the turn is busted. A busted turn results in the turned being scored as 0.
Rolls and scores will usually be balanced; The dice are rolled, and then a portion of the rolled dice a scored. The exception is a busted turn. Since there is no way to score, the final roll, the number of rolls will be one more than the number of scores.
-
complete¶ bool – True of the turn is finished (either banked or busted)
-
pid¶ int – Indicates the player playing the turn
-
dice_score_pairs¶ list[tuple[tuple[int], int]] – Items in this list are tuples of the dice that were scored after each roll and the corresponding score
-
roll_hist¶ list[tuple[int]] – History of rolls. Scored dice must be a subset of rolled dice.
-
min_bank¶ int – Minimum running total for a turn required to bank
-
FIRST_DICE_COUNT= 6¶ int – Number of dice to roll at the beginning of a turn
-
busted¶ bool – True if there is no way to score with the last roll
-
min_scorable¶ tuple[tuple[int], int] – Best score with the least number of dice
-
rolled¶ tuple[int] – The last roll of the dice
-
score¶ int – The score for the last scored dice
-
scored_dice¶ int – The score for the last scored dice
-
scores¶ int – The score for the last scored dice
-
subscores¶ dict[str, int] – Scores for sub-combos of rolled
-
total¶ int – Total of the scored dice, or 0 if busted
-
thekraf.score¶
Logic related to scoring dice and caching scores
-
class
thekraf.score.BaseScore[source]¶ Bases:
object-
classmethod
calc_of_a_kind(opts, n, val)[source]¶ Calculate score for n of a kind where n >= 3
Parameters: Returns: The score for n dice of value val
Return type:
-
classmethod
gen_all_dice_strs()[source]¶ Generate all possible dice combos as strings
Yields: str – Dice represented by a string
-
classmethod
score_all(*args, **kwargs)¶
-
classmethod
-
class
thekraf.score.Score[source]¶ Bases:
thekraf.score.ScoreCache,thekraf.score.BaseScoreLogic related to scoring dice
-
classmethod
calc_score(*args, **kwargs)¶
-
classmethod
subscores(*args, **kwargs)¶
-
classmethod
-
class
thekraf.score.ScoreCache[source]¶ Bases:
thekraf.score.BaseScoreLogic for creating and saving the score caches
-
classmethod
create_score_any_by_num_cache(score_any_cache)[source]¶ Organize the score any cache by number of dice
Examples
>>> d = cfg.load_config_item( 'score_options', select=lambda x: x['name'] == 'default')[0] >>> opts = mdls.ScoreOptions(**d) >>> cls = ScoreCache >>> cls.precache_scores(opts) >>> cache = opts.score_any_by_num_cache >>> sum(map(len, cache.values())) == len(opts.score_any_cache) True
Parameters: score_any_cache (dict[str, dict[str, int]]) – The score any cache Returns: Organized cache Return type: dict[int, dict[str, dict[str, int]]]
-
classmethod
create_score_any_cache(score_cache)[source]¶ Create cache of possible ways to score with sub-combos of dice
Sub-combo also includes all of the dice. If none of the sub-combos are in
_score_cache, it will not be included (see examples).Returns: - Dict from string rep of dice to sub-dict
- of
_score_cache
Return type: dict[str, dict[str, int] Raises: AssertionError– If_score_cachehasn’t been initializedExamples
>>> d = [a for a in cfg.load_config_item('score_options') if a['name'] == 'default'][0] >>> opts = mdls.ScoreOptions(**d) >>> score_cache = ScoreCache.create_score_cache(opts) >>> cls = ScoreCache >>> cache = cls.create_score_any_cache(score_cache) >>> '1' in cache['12'] True >>> '2' in cache['12'] False >>> '12' in cache['12'] False
>>> '11' in cache['11'] True >>> '1' in cache['1'] True
-
classmethod
create_score_cache(opts)[source]¶ Create cache of possible scores in which all dice score
If any of the dice are non-scoring, the score would be zero, so it isn’t in the cache (see examples).
Parameters: opts (thekraf.config.ScoreOptions) – Scoring options Returns: Dict from string rep of dice to score Return type: dict[str, int] Examples
>>> d = [a for a in cfg.load_config_item('score_options') if a['name'] == 'default'][0] >>> opts = mdls.ScoreOptions(**d) >>> cache = ScoreCache.create_score_cache(opts) >>> cache['1'] 100 >>> '2' in cache False
Since all dice have to be scoring...
>>> '12' in cache False
-
classmethod
thekraf.utils¶
Miscellaneous utilities
-
class
thekraf.utils.MixedHelpFormatter(prog, indent_increment=2, max_help_position=24, width=None)[source]¶ Bases:
argparse.ArgumentDefaultsHelpFormatter,argparse.RawDescriptionHelpFormatterCombo of arg default and raw description help formatters
-
class
thekraf.utils.MutableList[source]¶ Bases:
sqlalchemy.ext.mutable.Mutable,listList type for SQLAlchemy with changed state for the session
-
thekraf.utils.get_subclasses(cls)[source]¶ Get all subclasses of cls, recursively
If A is a subclass of cls and B is a subclass of A, both A and B will be include
Note
Does not include cls itself
Parameters: cls (type) – Returns: Return type: tuple[type]
-
thekraf.utils.recreate_field(unbound_field)[source]¶ Make a copy of an unbound field that bumps the creation counter
WTForms determines the order of the fields of form with a creation counter that is increment during the unbound field init. The issue is that the fields of subclasses of a form are created after their super classes so the subclass fields are always appended. That is, unless you override a field, but that can be a lot of work.
If a subclass overrides a parent field by sending it through this function, a copy of the unbound field will be created it an updated creation count so the subclass can dictate the order of the fields.
Parameters: unbound_field (wtforms.UnboundField) – The field to copy Returns: Copy of the field Return type: wtforms.UnboundField
Database¶
thekraf.db¶
Database models, ORM, and other configuration
Overview¶
thekraf.db.model defines models that are mostly pure Python. Then,
thekraf.db.mapper configures those models to be accessible via
the sqlalchemy ORM. Separating these roles, allows for the possibility of
implementation of additional ORMs in the future.
thekraf.db.listeners¶
A collection of SQLAlchemy event listeners to be applied to mapped models
Note
SQLAlchemy will ignore fields that don’t exist on the target
thekraf.db.mapper¶
Object-relational mapping of models for SQLAlchemy
-
thekraf.db.mapper.config_metadata()[source]¶ Configure the metadata for the ORM
This metadata may then be used to configure the database manager
Returns: The configured metadata Return type: MetaData
-
thekraf.db.mapper.config_sqla_models(models, dbm)[source]¶ Configure basic models for SQLAlchemy
Note
This can only be called after the metadata and the database manager have been configured.
Parameters: - models (tuple[BaseModel]) – Models to config
- dbm (DatabaseManager) – The database manager providing the session factory
thekraf.db.models¶
Models for the database
-
class
thekraf.db.models.Role(**kwargs)[source]¶ Bases:
thekraf.db.models.BaseModel,flask_security.core.RoleMixin-
created¶
-
description¶
-
id¶
-
modified¶
-
name¶
-
query= <sqlalchemy.orm.query.Query object>¶
-
users¶
-
-
class
thekraf.db.models.ScoreOptions(**kwargs)[source]¶ Bases:
thekraf.db.models.BaseModelConfigurable scoring options
-
name¶ str – Name of these options
-
description¶ str – Description of these options
-
single1¶ int – A single die of value 1
-
single5¶ int – A single die of value 5
-
triple1¶ int – A triplet of dice of value 1 (usually 300 or 1000)
-
fourplusscheme¶ str – Scoring scheme for 4-6 of a kind
-
kind4¶ int – Score for 4 of a kind when using the ‘set’ scheme
-
kind5¶ int – Score for 5 of a kind when using the ‘set’ scheme
-
kind6¶ int – Score for 6 of a kind when using the ‘set’ scheme
-
straight¶ int – Score for a straight (123456)
-
threepair¶ int – Score for three pairs (e.g. 112233)
-
twotriplets¶ int – Score of two triplets (e.g. 111222) (instead of scoring each triplet on its own)
-
fullhousebonus¶ int – Score a triplet and pair together as the triplet score plus this bonus (instead of scoring the pair on its own)
-
kind4bonus¶ int – Score a 4 of a kind and a pairs together as the 4 of a kind plus this bonus (instead of scoring the pair on its own)
-
points¶ int – Goal in points-based mode
-
score_cache¶ dict[str, int] – dice_str -> score, if all dice are scoring
-
score_any_cache¶ dict[str, dict[str, int]] – dice_str -> sub-dict of score_cache. The sub-keys will be sub-combos of dice_str in score_cache (meaning the sub-combo comprises all scoring dice.
-
score_any_by_num_cache¶ dict[int, dict[str, dict[str, int]]] – The score_any_cache organized by the number of dice.
-
ev_cache¶ dict[tuple[int, int], Decimal] – (pts, n) -> related ev
-
ADD_SCHEME= 'add'¶ str – Add triplet value for each die more than 3
Example
3 of a kind -> 1000, 4 -> 2000, 5 -> 3000, 6 -> 4000
-
DEFAULTS= {'name': '(unnamed)', 'straight': 2500, 'triple1': 1000, 'kind4': 2000, 'single1': 100, 'kind6': 6000, 'points': 10000, 'kind5': 4000, 'threepair': 1500, 'description': '', 'single5': 50, 'fourplusscheme': 'add'}¶
-
DOUBLE_SCHEME= 'double'¶ str – Double triplet value for each die more than 3
Example
3 of a kind -> 1000, 4 -> 2000, 5 -> 4000, 6 -> 8000
-
SET_SCHEME= 'set'¶ str – Use set values (kind4, kind5, kind6) regardless of die value
-
created¶
-
description
-
ev_cache
-
fourplusscheme
-
fullhousebonus
-
id¶
-
kind4
-
kind4bonus
-
kind5
-
kind6
-
modified¶
-
name
-
points
-
query= <sqlalchemy.orm.query.Query object>¶
-
score_any_by_num_cache
-
score_any_cache
-
score_cache
-
single1
-
single5
-
straight
-
threepair
-
triple1
-
twotriplets
-
Web¶
Init¶
thekraf.flaskapp¶
Flask web backend app
-
class
thekraf.flaskapp.FlaskWithHamlish(import_name, static_path=None, static_url_path=None, static_folder='static', template_folder='templates', instance_path=None, instance_relative_config=False)[source]¶ Bases:
flask.app.FlaskAdds support for Hamlish-Jinja to Flask
-
jinja_options= ImmutableDict({'extensions': ['jinja2.ext.autoescape', 'jinja2.ext.with_', 'hamlish_jinja.HamlishExtension']})¶
-
-
class
thekraf.flaskapp.JSONEncoderWrapper[source]¶ Bases:
objectAdd support for more types to the json encoder
if default and for_json are used, then if an object has a for_json attribute, it will be used. Otherwise, it will fallback on default
- flask uses a TaggedJSONSerializer on sessions which will be try
- converting various types before giving default a try.
Views¶
thekraf.flaskapp.baseview¶
The base for all flaskapp views
-
class
thekraf.flaskapp.baseview.ViewBase[source]¶ Bases:
flask.views.MethodViewMethodView with contexts for backend template and frontend
- Subclasses should subclass TemplateContext to add additional items to the context.
- Update the frontend dict with
ctx.update_frontend(d). This method is equivalent todict.update(). ctx.frontendwill become the json string, and this is done automatically by the base view. There is no reason to access this attr from a subclass.
The frontend data is collected in a python dict. One of the final stages of rendering is to dump this dict as a string of json and save it to
ctx.frontend. Then, the base template creates a javascript script in whichctxis set to the json data. Then, the frontend can access this data via thectxnamespace.-
ctx¶ ViewBase.TemplateContext – Context for project-specific data to be available from the backend template
-
classmethod
ViewBase.ctx_processor()[source]¶ Context processor for use with Flask-Security
When customizing the Flask-Security views, this context processor must be added so the template context includes data available to all other views.
Returns: Dict of keyword args included with flask.render Return type: dict
-
ViewBase.get()[source]¶ Override with specific code for GET action
Override should end by returning
self.render()
-
ViewBase.methods= ['GET', 'POST']¶
-
ViewBase.post()[source]¶ Override with specific code for POST action
Override should end by returning
self.render()orself.redirect_to_get()
-
classmethod
ViewBase.redirect_to_get(endpoint=None)[source]¶ Redirect a POST action to the equivalent GET
After a POST action, reloading the page results in the “Are you sure you want to send a form again?” dialog. One way to avoid this often annoying occurrence is to redirect to the equivalent GET.
Notes
The POST data is lost upon redirect, so this only works if the POST data has been processed before the redirect.
View Helpers¶
thekraf.flaskapp.fields¶
Fields used by thekraf.flaskapp.forms
-
class
thekraf.flaskapp.fields.BooleanFieldList(unbound_field, label=None, validators=None, min_entries=0, max_entries=None, default=(), **kwargs)[source]¶ Bases:
wtforms.fields.core.FieldList-
widget= <thekraf.flaskapp.widgets.BootstrapButtonGroupWidget object>¶
-
-
class
thekraf.flaskapp.fields.CheckboxField(label=None, validators=None, **kwargs)[source]¶ Bases:
wtforms.fields.core.FieldCheckbox input with checked state separate from value
Represents an
<input type="checkbox">. If the default value is a tuple, the first item will become value, and the second item is a boolean indicating the initialcheckedstate. When form data is parsed, onlycheckedfields will be included (that is how HTML is designed).-
widget= <thekraf.flaskapp.widgets.CheckboxValueInput object>¶
-
thekraf.flaskapp.formatters¶
Functions to format model data for the backend templates
-
thekraf.flaskapp.formatters.score_opts_def_pairs(opts)[source]¶ Attr name / value pairs of specific opts
Parameters: opts (ScoreOptions) – Scoring options Returns: Attr name / value pairs Return type: tuple[tuple[str, str]]
thekraf.flaskapp.forms¶
Flask-WTF forms used by the flask app
-
class
thekraf.flaskapp.forms.Form(formdata=<class 'flask_wtf.form._Auto'>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]¶ Bases:
flask_wtf.form.Form-
ACTION_SUFFIX= '_button'¶
-
-
class
thekraf.flaskapp.forms.GameForm(formdata=<class 'flask_wtf.form._Auto'>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]¶ Bases:
thekraf.flaskapp.forms.Form-
mode_select= <UnboundField(SelectField, ('Mode',), {'choices': [('rounds', 'Rounds'), ('points', 'Points')]})>¶
-
opts_select= <UnboundField(SelectField, ('Scoring Config',), {'choices': []})>¶
-
player_name_input= <UnboundField(StringField, ('Player Names',), {'render_kw': {'placeholder': 'Player 1, Player 2, ...'}})>¶
-
user_select= <UnboundField(BooleanFieldList, (<UnboundField(CheckboxField, (), {'render_kw': {'autocomplete': 'off'}})>,), {'label': 'Players', 'render_kw': {'_btn_styles': ('default',), '_btn_group_styles': ('vertical',)}})>¶
-
-
class
thekraf.flaskapp.forms.LoginUserForm(*args, **kwargs)[source]¶ Bases:
flask_security.forms.LoginForm-
email= <UnboundField(StringField, ('E-mail/Username',), {'validators': (<wtforms.validators.DataRequired object at 0x7f6fb55bbb00>,)})>¶
-
password= <UnboundField(PasswordField, ('Password',), {'validators': (<wtforms.validators.DataRequired object at 0x7f6fb55bbc18>,)})>¶
-
remember= <UnboundField(BooleanField, ('Remember Me',), {})>¶
-
submit= <UnboundField(SubmitField, ('Login',), {})>¶
-
-
class
thekraf.flaskapp.forms.OptsForm(formdata=<class 'flask_wtf.form._Auto'>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]¶ Bases:
thekraf.flaskapp.forms.Form-
opts_select= <UnboundField(SelectField, ('Scoring Config',), {'choices': []})>¶
-
submit= <UnboundField(SubmitField, ('Load',), {})>¶
-
-
class
thekraf.flaskapp.forms.RegisterUserForm(*args, **kwargs)[source]¶ Bases:
flask_security.forms.RegisterForm-
email= <UnboundField(StringField, ('Email Address',), {'validators': [<flask_security.forms.Required object at 0x7f6fb5e870f0>, <flask_security.forms.Email object at 0x7f6fb5e87160>, <function unique_user_email at 0x7f6fb5ddbae8>]})>¶
-
first= <UnboundField(StringField, ('First Name *',), {'validators': (<wtforms.validators.DataRequired object at 0x7f6fb55c1080>,)})>¶
-
last= <UnboundField(StringField, ('Last Name *',), {'validators': (<wtforms.validators.DataRequired object at 0x7f6fb55c1160>,)})>¶
-
nickname= <UnboundField(StringField, ('Nickname',), {'validators': (<wtforms.validators.Optional object at 0x7f6fb55c1240>,)})>¶
-
password= <UnboundField(PasswordField, ('Password',), {'validators': [<flask_security.forms.Required object at 0x7f6fb5e87438>, <flask_security.forms.Length object at 0x7f6fb5e87470>]})>¶
-
password_confirm= <UnboundField(PasswordField, ('Retype Password',), {'validators': [<flask_security.forms.EqualTo object at 0x7f6fb5e51e80>]})>¶
-
submit= <UnboundField(SubmitField, ('Register',), {})>¶
-
username= <UnboundField(StringField, ('Username',), {'validators': (<wtforms.validators.Optional object at 0x7f6fb55bbe80>,)})>¶
-
-
class
thekraf.flaskapp.forms.ScoreForm(formdata=<class 'flask_wtf.form._Auto'>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]¶ Bases:
thekraf.flaskapp.forms.Form-
dice_input= <UnboundField(StringField, ('Dice Repr',), {})>¶
-
submit= <UnboundField(SubmitField, ('Score',), {})>¶
-
-
class
thekraf.flaskapp.forms.TurnForm(formdata=<class 'flask_wtf.form._Auto'>, obj=None, prefix='', csrf_context=None, secret_key=None, csrf_enabled=None, *args, **kwargs)[source]¶ Bases:
thekraf.flaskapp.forms.Form-
dice_select= <UnboundField(BooleanFieldList, (<UnboundField(CheckboxField, (), {'render_kw': {'autocomplete': 'off'}})>,), {'label': 'Select Dice', 'render_kw': {'_btn_styles': ('primary btn-dice',), '_btn_group_styles': ('lg',)}})>¶
-
scored_select= <UnboundField(BooleanFieldList, (<UnboundField(CheckboxField, (), {'render_kw': {'autocomplete': 'off'}})>,), {'label': 'Scored Dice', 'render_kw': {'_btn_styles': ('success',), '_btn_group_styles': ('lg',)}})>¶
-
thekraf.flaskapp.widgets¶
Widgets used by thekraf.flaskapp.fields
-
class
thekraf.flaskapp.widgets.BootstrapButtonGroupWidget[source]¶ Bases:
objectRenders a Bootstrap 3 checkbox/radio button group
-
class
thekraf.flaskapp.widgets.CheckboxValueInput(input_type=None)[source]¶ Bases:
wtforms.widgets.core.InputRender a checkbox with checked state separate from value
The
checkedHTML attribute is set if field.checked is a non-false value. The value of the input doesn’t change. This allows using the value in labeling the field.Note
HTML will only return checkbox inputs that are checked upon submit.
-
input_type= 'checkbox'¶
-
App¶
thekraf.flaskapp.app¶
Create and configure the global app instance
Production servers usually need to access the global app instance.
-
thekraf.flaskapp.app.app= <FlaskWithHamlish 'thekraf.flaskapp'>¶ flask.Flask – Global flask app instance
Paths¶
- static/:
- Static resources available to the client
- static/frontend/:
- Frontend code
- templates/:
- Backend templates
- package.json:
- This defines the nodejs dependencies to install when
node installis run - package.yaml:
- YAML version of package.json. Advantageous since it allows comments. However, it must be converted to package.json before it can be used.
- webpack.config.js:
- Configuration file that is interrogated when
webpackis run. The result is static/bundle.js.