Skip to content

Commit 8221a75

Browse files
authored
Merge pull request #8 from Bernardo-MG/merge_master
Merge master
2 parents 9c8c206 + c9f3c56 commit 8221a75

52 files changed

Lines changed: 2105 additions & 73 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ matrix:
2424
# Tests and deploys docs, also runs coverage report
2525
- python: "3.5"
2626
env: COVERAGE=true TEST_DOCS=true DEPLOY_DOCS=true
27+
addons:
28+
apt:
29+
packages:
30+
- sshpass
2731

2832
before_install:
2933
# Gets scripts
30-
- git clone -b v0.2.0 --single-branch https://github.com/Bernardo-MG/ci-shell-scripts.git ~/.scripts
34+
- git clone -b v0.4.0 --single-branch https://github.com/Bernardo-MG/ci-shell-scripts.git ~/.scripts
3135
# Sets scripts as executable
3236
- chmod -R +x ~/.scripts/*
3337
# Prepares CI environment
@@ -36,6 +40,10 @@ before_install:
3640
install:
3741
# tox is required for the tests
3842
- pip install tox
43+
# sphinx is required for the docs
44+
- pip install sphinx
45+
# Dependencies
46+
- pip install --upgrade -r requirements.txt
3947
script:
4048
# Code is checked
4149
- ~/.scripts/python/run_tests.sh true check
@@ -47,4 +55,7 @@ script:
4755
- ~/.scripts/python/run_tests.sh $DO_COVERAGE coverage
4856
after_success:
4957
# Documentation deployment
50-
- ~/.scripts/rtd/deploy.sh $DO_DEPLOY_DOCS dice-notation
58+
- ~/.scripts/sphinx/build-html.sh $DO_DEPLOY_DOCS docs
59+
- cd ~/sphinx/build/html
60+
- ~/.scripts/deploy/deploy-ssh.sh $DO_DEPLOY_DOCS_RELEASE $DEPLOY_USERNAME $DEPLOY_PASSWORD $DEPLOY_HOST $DEPLOY_PORT $DEPLOY_PATH_RELEASE
61+
- ~/.scripts/deploy/deploy-ssh.sh $DO_DEPLOY_DOCS_DEVELOP $DEPLOY_USERNAME $DEPLOY_PASSWORD $DEPLOY_HOST $DEPLOY_PORT $DEPLOY_PATH_DEVELOP

README.rst

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,19 @@ operating with it on any Python application.
1818
:target: https://pypi.python.org/pypi/dice-notation
1919
:alt: Dice Notation Tools for Python Pypi package page
2020

21-
.. image:: https://readthedocs.org/projects/dice-notation/badge/?version=latest
22-
:target: http://dice-notation.readthedocs.org/en/latest/
23-
:alt: Dice Notation Tools for Python latest documentation Status
24-
.. image:: https://readthedocs.org/projects/dice-notation/badge/?version=develop
25-
:target: http://dice-notation.readthedocs.org/en/develop/
26-
:alt: Dice Notation Tools for Python development documentation Status
21+
.. image:: https://img.shields.io/badge/docs-release-blue.svg
22+
:target: http://docs.wandrell.com/dice-notation-python
23+
:alt: Dice Notation Tools for Python latest documentation
24+
.. image:: https://img.shields.io/badge/docs-develop-blue.svg
25+
:target: http://docs.wandrell.com/development/dice-notation-python/
26+
:alt: Dice Notation Tools for Python development documentation
2727

2828
Features
2929
--------
3030

31-
The library contains the following features:
32-
33-
- API for dice and dice notation, along classes to generate values from them
34-
- Parser to create API instances from the notation
31+
- Ply-based parser to generate objects for dice notation
32+
- Easy-to-use objects to handle the notation, just call the 'roll' method
33+
- Classes to support plain dice
3534

3635
Documentation
3736
-------------
@@ -43,7 +42,7 @@ documentation sites:
4342
- The `development docs`_ are generated from the latest code in the 'develop' branch
4443

4544
You can also create the documentation from the source files, kept in the 'docs'
46-
folder, with the help of Sphinx. For this use the makefile, or the make.bat
45+
folder, with the help of `Sphinx`_. For this use the makefile, or the make.bat
4746
file, contained on that folder.
4847

4948
Prerequisites
@@ -80,9 +79,24 @@ the following command:
8079
Usage
8180
-----
8281

83-
The application has been coded in Python, without using any particular
82+
The application has been coded in Python, and does not require any particular
8483
framework.
8584

85+
To use it just import the parser::
86+
87+
from dice_notation.parser import DiceParser
88+
89+
And then use it to parse a dice notation expression::
90+
91+
parser = DiceParser()
92+
dice = parser.parse('1d6+2')
93+
94+
The result can be accessed just by calling the 'roll' method as many times as
95+
needed, which will generate a new random value each time it is called::
96+
97+
print(dice.roll())
98+
print(dice.roll())
99+
86100
Collaborate
87101
-----------
88102

@@ -109,10 +123,10 @@ License
109123

110124
The project has been released under the `MIT License`_.
111125

112-
.. _GitHub project page: https://github.com/Bernardo-MG/dice-notation
113-
.. _latest docs: http://dice-notation.readthedocs.org/en/latest/
114-
.. _development docs: http://dice-notation.readthedocs.org/en/develop/
126+
.. _GitHub project page: https://github.com/Bernardo-MG/dice-notation-python
127+
.. _latest docs: http://docs.wandrell.com/dice-notation-python/
128+
.. _development docs: http://docs.wandrell.com/development/dice-notation-python/
115129
.. _Pypi package: https://pypi.python.org/pypi/dice-notation
116130
.. _MIT License: http://www.opensource.org/licenses/mit-license.php
117-
.. _project issues tracker: https://github.com/Bernardo-MG/dice-notation/issues
131+
.. _project issues tracker: https://github.com/Bernardo-MG/dice-notation-python/issues
118132
.. _Sphinx: http://sphinx-doc.org/

dice-notation/__main__.py

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
:license: MIT, see LICENSE for more details.
88
"""
99

10-
__version__ = '0.1.0'
10+
__version__ = '1.0.0'
1111
__license__ = 'MIT'

dice_notation/dice.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import sys
4+
from abc import ABCMeta, abstractmethod
5+
from random import randint
6+
7+
"""
8+
Dice classes.
9+
10+
These are just plain dice, not dice notation, even thought they may be used
11+
for handling that too.
12+
13+
The classes in this file will allow creating and using dice and rollable
14+
entities, which are able to generate a random value.
15+
16+
There are two dice classes, the Dice is just the bare dice, while the
17+
RollableDice is an extension, which allows rolling the dice.
18+
"""
19+
20+
__author__ = 'Benardo Martínez Garrido'
21+
__license__ = 'MIT'
22+
23+
if sys.version_info[0] >= 3:
24+
xrange = range
25+
26+
27+
class Rollable(object):
28+
"""
29+
Interface for rollable classes.
30+
31+
While rolling implies using dice to generate a random value, this interface
32+
just takes care of generating a random value.
33+
34+
This way it not only can support any kind of dice, but also more complex
35+
constructions such as dice notation expressions, where calling the roll
36+
method would execute the full expression.
37+
38+
As such, the value generated by rolling may be anything.
39+
"""
40+
__metaclass__ = ABCMeta
41+
42+
def __init__(self):
43+
pass
44+
45+
@abstractmethod
46+
def roll(self):
47+
"""
48+
Generates a random value.
49+
50+
This can be anything, the only expectation is that the output
51+
is randomized somehow.
52+
"""
53+
raise NotImplementedError('The roll method must be implemented')
54+
55+
56+
class Dice(object):
57+
"""
58+
A group of dice, all with the same number of sides. Such a group is just
59+
composed of a quantity of dice, and their number of sides.
60+
61+
Both the quantity and the number of sides are expected to be positive, as
62+
any other value would make no sense.
63+
64+
No other limitation is expected. In the real world the number of sides
65+
which a die may physically have are limited by the rules of geometry,
66+
but there is no reason to take care of that.
67+
"""
68+
69+
def __init__(self, quantity, sides):
70+
super(Dice, self).__init__()
71+
self._quantity = quantity
72+
self._sides = sides
73+
74+
def __str__(self):
75+
return '%sd%s' % (self.quantity, self.sides)
76+
77+
def __repr__(self):
78+
return '<class %s>(quantity=%r, sides=%r)' % \
79+
(self.__class__.__name__, self.quantity, self.sides)
80+
81+
@property
82+
def quantity(self):
83+
"""
84+
The number of dice which compose this group.
85+
86+
This is expected to be a positive value or zero.
87+
88+
:return: the number of dice
89+
"""
90+
return self._quantity
91+
92+
@quantity.setter
93+
def quantity(self, quantity):
94+
self._quantity = quantity
95+
96+
@property
97+
def sides(self):
98+
"""
99+
The number of sides each die has.
100+
101+
All the dice in the group have the same number of sides.
102+
103+
This is expected to be a positive value or zero.
104+
105+
:return: the number of sides
106+
"""
107+
return self._sides
108+
109+
@sides.setter
110+
def sides(self, sides):
111+
self._sides = sides
112+
113+
114+
class RollableDice(Dice, Rollable):
115+
"""
116+
A rollable dice group.
117+
118+
The result of calling the roll method will be an integer, which will be
119+
between 1 and the number of sides. Actually one number will be generated
120+
like that as many times as the value of the quantity field, and all those
121+
values will be added, and then returned.
122+
"""
123+
124+
def __init__(self, quantity, sides):
125+
super(RollableDice, self).__init__(quantity, sides)
126+
127+
def roll(self):
128+
result = 0
129+
130+
if self.quantity == 0 or self.sides == 0:
131+
result = 0
132+
elif self.quantity is None or self.sides is None:
133+
result = None
134+
elif self.quantity > 0 and self.sides > 0:
135+
for x in xrange(self.quantity):
136+
result += randint(1, self.sides)
137+
else:
138+
result = None
139+
140+
return result

dice_notation/parser/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from dice_notation.parser.dice import DiceParser
4+
5+
__all__ = ['DiceParser']

dice_notation/parser/common.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import os
4+
from abc import ABCMeta, abstractmethod
5+
6+
import ply.lex as lex
7+
import ply.yacc as yacc
8+
9+
"""
10+
Base classes for parsers.
11+
12+
It contains some interfaces, along a base parser for the parsing library being
13+
used.
14+
"""
15+
16+
__author__ = 'Bernardo Martínez Garrido'
17+
__license__ = 'MIT'
18+
19+
20+
class Parser(object):
21+
"""
22+
Interface for implementing parsers.
23+
24+
It just contains a single method, 'parse', which will receive a value
25+
and take care of parsing it into another.
26+
"""
27+
28+
__metaclass__ = ABCMeta
29+
30+
def __init__(self):
31+
pass
32+
33+
@abstractmethod
34+
def parse(self, value):
35+
raise NotImplementedError('The parse method must be implemented')
36+
37+
38+
class PlyParser(Parser):
39+
"""
40+
Base class for a lexer/parser that has the rules defined as methods.
41+
42+
It makes use of Ply for the parsing.
43+
"""
44+
45+
tokens = ()
46+
precedence = ()
47+
48+
def __init__(self, **kw):
49+
super(PlyParser, self).__init__()
50+
self.debug = kw.get('debug', 0)
51+
self.names = {}
52+
try:
53+
modname = os.path.split(os.path.splitext(__file__)[0])[
54+
1] + "_" + self.__class__.__name__
55+
except:
56+
modname = "parser" + "_" + self.__class__.__name__
57+
self.debugfile = modname + ".dbg"
58+
self.tabmodule = modname + "_" + "parsetab"
59+
# print self.debugfile, self.tabmodule
60+
61+
# Builds the lexer and parser
62+
lex.lex(module=self, debug=self.debug)
63+
yacc.yacc(module=self,
64+
debug=self.debug,
65+
debugfile=self.debugfile,
66+
tabmodule=self.tabmodule)
67+
68+
def parse(self, value):
69+
return yacc.parse(value)

0 commit comments

Comments
 (0)