precommit git hooks, rearrange package structure (#251)

* precommit hooks and changes because of these
* mv package into src dir
* add requirements file, clean up setup reqs, add precommit to CI
This commit is contained in:
Peter 2019-05-23 16:17:30 -07:00 committed by GitHub
parent e859dc36ef
commit 31a71447f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
140 changed files with 1931 additions and 1289 deletions

6
.gitignore vendored
View File

@ -12,10 +12,10 @@ dist
.vscode
generated
domdiv/fonts/*.otf
domdiv/fonts/*.ttf
src/domdiv/fonts/*.otf
src/domdiv/fonts/*.ttf
dominion_dividers.pdf
dominion_dividers.png
tools/card_db
.mypy_cache/
.mypy_cache/

20
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,20 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
default_language_version:
# force all unspecified python hooks to run python3
python: python3
repos:
- repo: https://github.com/ambv/black
rev: 18.9b0
hooks:
- id: black
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.1.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: flake8
args: [--max-line-length=120, '--ignore=E203,W503']
- id: check-json
# - id: pretty-format-json
# args: [--autofix, --no-sort-keys]

View File

@ -6,5 +6,8 @@ python:
install:
- pip install -U setuptools
- pip install .
- pip install -r requirements.txt
# command to run tests
script: python setup.py test
script:
- python setup.py test
- if [[ ${TRAVIS_PYTHON_VERSION:0:1} == "3" ]]; then pre-commit run --all-files; fi

View File

@ -1,4 +1,5 @@
recursive-include domdiv/card_db *.json
include domdiv/images/*.png
include domdiv/fonts/*.ttf
graft src
global-exclude *.py[co]
global-exclude __pycache__
global-exclude .DS_Store
global-exclude *Minion*.[ot]tf

View File

@ -20,13 +20,7 @@ The script has an extensive set of options that are relatively well documented v
If you would like to help with translations to new (or updating existing) languages, please see [instructions here](https://github.com/sumpfork/dominiontabs/blob/master/domdiv/card_db/translation.md).
## Prerequisites
### Python Packages
You need the python packages for [reportlab](http://www.reportlab.com/software/opensource/rl-toolkit/download/) and [Pillow](https://pypi.org/project/Pillow/) installed. You can install them manually or use the included setup.py via 'python setup.py install' (perhaps run via 'sudo' if not in a virtual env) which should install everything for you.
### Fonts
## Fonts
I believe I cannot distribute one font (Minion Pro) domdiv uses as they are owned by Adobe with a License that I understand to disallow redistribution.
@ -48,8 +42,8 @@ The library will be installed as `domdiv` with the main entry point being `domdi
## Developing
You can use `python setup.py develop` to install the `dominion_dividers` script so that it calls your checked out code, enabling you to run edited code without having to perform an install every time.
Install requirements via `pip install -r requirements.txt`. Then, run `pre-commit install`. You can use `python setup.py develop` to install the `dominion_dividers` script so that it calls your checked out code, enabling you to run edited code without having to perform an install every time.
Feel free to comment on boardgamegeek at <https://boardgamegeek.com/thread/926575/web-page-generate-tabbed-dividers> or file issues on github (<https://github.com/sumpfork/dominiontabs/issues>).
Tests can be run (and their dependencies installed) via `python setup.py test`.
Tests can be run (and their dependencies installed) via `python setup.py test`, which will also happen if/when you push a branch or make a PR.

View File

@ -2,16 +2,16 @@ import domdiv
import domdiv.main
from zipfile import ZipFile, ZIP_DEFLATED
prefix = 'generated/sumpfork_dominion_tabs_'
postfix = 'v' + domdiv.__version__ + '.pdf'
prefix = "generated/sumpfork_dominion_tabs_"
postfix = "v" + domdiv.__version__ + ".pdf"
def doit(args, main):
args = args + ' --outfile ' + prefix + main + postfix
args = args + " --outfile " + prefix + main + postfix
args = args.split()
fname = args[-1]
print(args)
print(':::Generating ' + fname)
print(":::Generating " + fname)
options = domdiv.main.parse_opts(args)
options = domdiv.main.clean_opts(options)
domdiv.main.generate(options)
@ -19,20 +19,23 @@ def doit(args, main):
argsets = [
('', ''), ('--orientation=vertical', 'vertical_'),
('--papersize=A4', 'A4_'),
('--papersize=A4 --orientation=vertical', 'vertical_A4_'),
('--size=sleeved', 'sleeved_'),
('--size=sleeved --orientation=vertical', 'vertical_sleeved_')
("", ""),
("--orientation=vertical", "vertical_"),
("--papersize=A4", "A4_"),
("--papersize=A4 --orientation=vertical", "vertical_A4_"),
("--size=sleeved", "sleeved_"),
("--size=sleeved --orientation=vertical", "vertical_sleeved_"),
]
additional = ['--expansion-dividers']
additional = ["--expansion-dividers"]
fnames = [doit(args[0] + ' ' + ' '.join(additional), args[1])
for args in argsets]
fnames = [doit(args[0] + " " + " ".join(additional), args[1]) for args in argsets]
print(fnames)
zip = ZipFile('generated/sumpfork_dominion_tabs_v' + domdiv.__version__ + '.zip', 'w',
ZIP_DEFLATED)
zip = ZipFile(
"generated/sumpfork_dominion_tabs_v" + domdiv.__version__ + ".zip",
"w",
ZIP_DEFLATED,
)
for f in fnames:
zip.write(f)
zip.close()

View File

@ -1,2 +0,0 @@
import pkg_resources
__version__ = pkg_resources.require('domdiv')[0].version

View File

@ -1,4 +0,0 @@
#### Fonts
I believe I cannot distribute one font (Minion Pro) domdiv uses as they are commercially sold by Adobe. However, the font files are included with every install of the free Adobe Reader. For example, on Windows 7 they are in C:\Program Files (x86)\Adobe\Reader 9.0\Resource\Font called `MinionPro-Regular.otf`, `MinionPro-Bold.otf` and `MinionPro-It.otf`.
Sadly, these fonts use features of the otf format that are not support by the reportlab package. Thus, they need to first be converted to ttf (TrueType) format. I used the open source package fontforge to do the conversion. Included as 'convert.ff' is a script for fontforge to do the conversion, on Mac OS X with fontforge installed through macports you can just run `./convert.ff MinionPro-Regular.otf`, `./convert.ff MinionPro-Bold.otf` and `./convert.ff MinionPro-It.otf`. With other fontforge installations, you'll need to change the first line of convert.ff to point to your fontforge executable. I have not done this step under Windows - I imagine it may be possible with a cygwin install of fontforge or some such method. Copy these converted files to this subdirectory.

View File

@ -1,323 +0,0 @@
from .. import main
####################
# Card Text and Tab Default Test
####################
def test_text_tabs_default():
# should be the default
options = main.parse_opts([])
assert options.text_front == 'card'
assert options.text_back == 'rules'
assert options.tab_name_align == 'left'
assert options.tab_side == 'right-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
####################
# Card Text Tests
####################
def test_text_card_rules():
options = main.parse_opts(
['--front', 'card', '--back', 'rules'])
assert options.text_front == 'card'
assert options.text_back == 'rules'
def test_text_card_blank():
options = main.parse_opts(
['--front', 'card', '--back', 'blank'])
assert options.text_front == 'card'
assert options.text_back == 'blank'
def test_text_card_card():
options = main.parse_opts(
['--front', 'card', '--back', 'card'])
assert options.text_front == 'card'
assert options.text_back == 'card'
def test_text_card_none():
options = main.parse_opts(
['--front', 'card', '--back', 'none'])
assert options.text_front == 'card'
assert options.text_back == 'none'
def test_text_rules_rules():
options = main.parse_opts(
['--front', 'rules', '--back', 'rules'])
assert options.text_front == 'rules'
assert options.text_back == 'rules'
def test_text_rules_blank():
options = main.parse_opts(
['--front', 'rules', '--back', 'blank'])
assert options.text_front == 'rules'
assert options.text_back == 'blank'
def test_text_rules_card():
options = main.parse_opts(
['--front', 'rules', '--back', 'card'])
assert options.text_front == 'rules'
assert options.text_back == 'card'
def test_text_rules_none():
options = main.parse_opts(
['--front', 'rules', '--back', 'none'])
assert options.text_front == 'rules'
assert options.text_back == 'none'
def test_text_blank_rules():
options = main.parse_opts(
['--front', 'blank', '--back', 'rules'])
assert options.text_front == 'blank'
assert options.text_back == 'rules'
def test_text_blank_blank():
options = main.parse_opts(
['--front', 'blank', '--back', 'blank'])
assert options.text_front == 'blank'
assert options.text_back == 'blank'
def test_text_blank_card():
options = main.parse_opts(
['--front', 'blank', '--back', 'card'])
assert options.text_front == 'blank'
assert options.text_back == 'card'
def test_text_blank_none():
options = main.parse_opts(
['--front', 'blank', '--back', 'none'])
assert options.text_front == 'blank'
assert options.text_back == 'none'
####################
# Card Tab Tests
####################
# --tab_name_align left
def test_tab_left_left():
options = main.parse_opts(
['--tab-name-align', 'left', '--tab-side', 'left'])
assert options.tab_name_align == 'left'
assert options.tab_side == 'left'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
assert options.tab_side == 'left'
def test_tab_left_right():
options = main.parse_opts(
['--tab-name-align', 'left', '--tab-side', 'right'])
assert options.tab_name_align == 'left'
assert options.tab_side == 'right'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
assert options.tab_side == 'right'
def test_tab_left_leftalt():
options = main.parse_opts(
['--tab-name-align', 'left', '--tab-side', 'left-alternate'])
assert options.tab_name_align == 'left'
assert options.tab_side == 'left-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
assert options.tab_side == 'left-alternate'
def test_tab_left_rightalt():
options = main.parse_opts(
['--tab-name-align', 'left', '--tab-side', 'right-alternate'])
assert options.tab_name_align == 'left'
assert options.tab_side == 'right-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
assert options.tab_side == 'right-alternate'
def test_tab_left_full():
options = main.parse_opts(
['--tab-name-align', 'left', '--tab-side', 'full'])
assert options.tab_name_align == 'left'
assert options.tab_side == 'full'
main.calculate_layout(options)
assert options.tab_name_align == 'left'
assert options.tab_side == 'full'
# --tab_name_align right
def test_tab_right_left():
options = main.parse_opts(
['--tab-name-align', 'right', '--tab-side', 'left'])
assert options.tab_name_align == 'right'
assert options.tab_side == 'left'
main.calculate_layout(options)
assert options.tab_name_align == 'right'
assert options.tab_side == 'left'
def test_tab_right_right():
options = main.parse_opts(['--tab-name-align', 'right', '--tab-side', 'right'])
assert options.tab_name_align == 'right'
assert options.tab_side == 'right'
main.calculate_layout(options)
assert options.tab_name_align == 'right'
assert options.tab_side == 'right'
def test_tab_right_leftalt():
options = main.parse_opts(
['--tab-name-align', 'right', '--tab-side', 'left-alternate'])
assert options.tab_name_align == 'right'
assert options.tab_side == 'left-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'right'
assert options.tab_side == 'left-alternate'
def test_tab_right_rightalt():
options = main.parse_opts(
['--tab-name-align', 'right', '--tab-side', 'right-alternate'])
assert options.tab_name_align == 'right'
assert options.tab_side == 'right-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'right'
assert options.tab_side == 'right-alternate'
def test_tab_right_full():
options = main.parse_opts(
['--tab-name-align', 'right', '--tab-side', 'full'])
assert options.tab_name_align == 'right'
assert options.tab_side == 'full'
main.calculate_layout(options)
assert options.tab_name_align == 'right'
assert options.tab_side == 'full'
# --tab_name_align edge
def test_tab_edge_left():
options = main.parse_opts(
['--tab-name-align', 'edge', '--tab-side', 'left'])
assert options.tab_name_align == 'edge'
assert options.tab_side == 'left'
main.calculate_layout(options)
assert options.tab_name_align == 'edge'
assert options.tab_side == 'left'
def test_tab_edge_right():
options = main.parse_opts(
['--tab-name-align', 'edge', '--tab-side', 'right'])
assert options.tab_name_align == 'edge'
assert options.tab_side == 'right'
main.calculate_layout(options)
assert options.tab_name_align == 'edge'
assert options.tab_side == 'right'
def test_tab_edge_leftalt():
options = main.parse_opts(
['--tab-name-align', 'edge', '--tab-side', 'left-alternate'])
assert options.tab_name_align == 'edge'
assert options.tab_side == 'left-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'edge'
assert options.tab_side == 'left-alternate'
def test_tab_edge_rightalt():
options = main.parse_opts(
['--tab-name-align', 'edge', '--tab-side', 'right-alternate'])
assert options.tab_name_align == 'edge'
assert options.tab_side == 'right-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'edge'
assert options.tab_side == 'right-alternate'
def test_tab_edge_full():
options = main.parse_opts(
['--tab-name-align', 'edge', '--tab-side', 'full'])
assert options.tab_name_align == 'edge'
assert options.tab_side == 'full'
options = main.clean_opts(options)
main.calculate_layout(options)
assert options.tab_name_align == 'left' # special check for odd condition
assert options.tab_side == 'full'
# --tab_name_align centre
def test_tab_centre_left():
options = main.parse_opts(['--tab-name-align', 'centre', '--tab-side', 'left'])
assert options.tab_name_align == 'centre'
assert options.tab_side == 'left'
main.calculate_layout(options)
assert options.tab_name_align == 'centre'
assert options.tab_side == 'left'
def test_tab_centre_right():
options = main.parse_opts(['--tab-name-align', 'centre', '--tab-side', 'right'])
assert options.tab_name_align == 'centre'
assert options.tab_side == 'right'
main.calculate_layout(options)
assert options.tab_name_align == 'centre'
assert options.tab_side == 'right'
def test_tab_centre_leftalt():
options = main.parse_opts(
['--tab-name-align', 'centre', '--tab-side', 'left-alternate'])
assert options.tab_name_align == 'centre'
assert options.tab_side == 'left-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'centre'
assert options.tab_side == 'left-alternate'
def test_tab_centre_rightalt():
options = main.parse_opts(
['--tab-name-align', 'centre', '--tab-side', 'right-alternate'])
assert options.tab_name_align == 'centre'
assert options.tab_side == 'right-alternate'
main.calculate_layout(options)
assert options.tab_name_align == 'centre'
assert options.tab_side == 'right-alternate'
def test_tab_centre_full():
options = main.parse_opts(['--tab-name-align', 'centre', '--tab-side', 'full'])
assert options.tab_name_align == 'centre'
assert options.tab_side == 'full'
main.calculate_layout(options)
assert options.tab_name_align == 'centre'
assert options.tab_side == 'full'
# --tab_name_align center. Just do one since this is an alias to centre
def test_tab_center_left():
options = main.parse_opts(['--tab-name-align', 'center', '--tab-side', 'left'])
assert options.tab_name_align == 'center'
assert options.tab_side == 'left'
options = main.clean_opts(options)
main.calculate_layout(options)
assert options.tab_name_align == 'centre' # check for change in value
assert options.tab_side == 'left'

5
requirements.in Normal file
View File

@ -0,0 +1,5 @@
reportlab
Pillow
pre-commit
pytest
six

25
requirements.txt Normal file
View File

@ -0,0 +1,25 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt requirements.in
#
aspy.yaml==1.1.1 # via pre-commit
atomicwrites==1.2.1 # via pytest
attrs==18.2.0 # via pytest
cfgv==1.4.0 # via pre-commit
identify==1.1.8 # via pre-commit
importlib-metadata==0.8 # via pre-commit
more-itertools==5.0.0 # via pytest
nodeenv==1.3.3 # via pre-commit
pillow==5.4.1
pluggy==0.8.1 # via pytest
pre-commit==1.14.2
py==1.7.0 # via pytest
pytest==4.1.1
pyyaml==3.13 # via aspy.yaml, pre-commit
reportlab==3.5.12
six==1.12.0
toml==0.10.0 # via pre-commit
virtualenv==16.2.0 # via pre-commit
zipp==0.3.3 # via importlib-metadata

View File

@ -1,9 +1,11 @@
[metadata]
description-file = README.md
[tool:pytest]
python_files=*tests.py
python_files = *tests.py
addopts = --flake8
testpaths = tests
[aliases]
test=pytest
test = pytest
[flake8]
max-line-length=120
max-line-length = 120
ignore = E203,W503

View File

@ -1,26 +1,22 @@
from setuptools import setup, find_packages
from setuptools import setup
version = '3.7.1'
version = "3.7.1"
setup(
name="domdiv",
version=version,
entry_points={
'console_scripts': [
"dominion_dividers = domdiv.main:main"
],
},
packages=find_packages(exclude=['tests']),
install_requires=["reportlab==3.5.17",
"Pillow==5.3.0"],
entry_points={"console_scripts": ["dominion_dividers = domdiv.main:main"]},
package_dir={"": "src"},
packages=["domdiv"],
install_requires=["reportlab==3.5.17", "Pillow==5.4.1"],
setup_requires=["pytest-runner"],
tests_require=["pytest", "pytest-flake8", "six"],
url='http://domtabs.sandflea.org',
tests_require=["pytest", "six", "pytest-flake8", "pre-commit"],
url="http://domtabs.sandflea.org",
include_package_data=True,
author="Peter Gorniak",
author_email="sumpfork@mailmight.net",
description="Divider Generation for the Dominion Card Game",
keywords=['boardgame', 'cardgame', 'dividers'],
keywords=["boardgame", "cardgame", "dividers"],
long_description="This script and library generate dividers for the Dominion Card Game by Rio Grande Games.\
See it in action at http://domtabs.sandflea.org."
See it in action at http://domtabs.sandflea.org.",
)

3
src/domdiv/__init__.py Normal file
View File

@ -0,0 +1,3 @@
import pkg_resources
__version__ = pkg_resources.require("domdiv")[0].version

View File

@ -1,7 +1,7 @@
{
"exclude": [
"Token",
"Tokens",
"Tokens",
"Marker"
],
"include": [
@ -16,4 +16,4 @@
"Punkt",
"Punkte"
]
}
}

View File

@ -18,4 +18,4 @@
"Villagers",
"<VP>"
]
}
}

View File

@ -19,4 +19,4 @@
"Actions",
"Action"
]
}
}

View File

@ -13,4 +13,4 @@
"Azioni",
"Azione"
]
}
}

View File

@ -19,7 +19,7 @@ The files:
cards_xx.json
sets_xx.json
types_xx.json
must be encoded in ISO 8859-15, also known as "Latin alphabet no. 9"
This character set is used throughout the Americas, Western Europe, Oceania, and much of Africa.
It is also commonly used in most standard romanizations of East-Asian languages.
@ -64,13 +64,13 @@ The items in the `include` list are items that will be marked **bold** (i.e., `<
when found in the card text in the following format:
`+# item_from_include_list`
as long as this is not followed by a item from the `exclude` list.
For example in English:
`+2 Buys` will be made bold, but
`+1 Action token` will not, since the key word token follows.
- Just replace the English terms with the terms used in the target language.
- Just replace the English terms with the terms used in the target language.
- Generally you should include the singular as well as the plural version of the term.
- English versions do not need to be duplicated, since they are used automatically.
- The key words `exclude` and `include` MUST NOT BE CHANGED.
@ -80,7 +80,7 @@ For example in English:
Entries in this file represent Dominion card types. A typical entry looks like:
"Action": "Action in new language",
- The type key word (i.e., the `Action` for the above entry) MUST NOT BE CHANGED. This value is used to identify the translation entry.
- Do not change any punctuation outside of the quotes `"`. For example, brackets `{` or `}`, colons `:`, quotes `"` or commas `,`.
@ -104,7 +104,7 @@ For example:
- if you provided the `name` of the card, and only the `name`, then change to `description, extra`
- if you provided the `name` of the card and it's `description`, but have not translated the `extra`, then change to `extra`
- if you provided all 3 entries, then change to `""`
The "untranslated" entry is used during maintanance of the language files to update any remaining default language entries that might have changed.
@ -154,28 +154,27 @@ IMPORTANT: To keep the special images, please do not translate any of the above
- If bonuses_xx.json for the target language is configured correctly, bonuses within the text will automatically be bolded.
In English, it will not bold the text if it is followed by `token` or `Token`. Example:
`Choose one: +3 Cards; or +2 Actions.` will bold `+3 Cards` and `+2 Actions`.
- Bonuses should be listed in the following order:
* `+ Cards`,
* `+ Actions`,
* `+ Buys`,
* `+ Coins`,
* `+ Actions`,
* `+ Buys`,
* `+ Coins`,
* `+ <VP>`
- When possible, bonuses should be listed vertically and centered. Examples:
* `+1 Card<br>+1 Action<br>+1 Buy<br>+1 Coin<br>+2 <VP><n>`
* `+1 Card\n+1 Action\n+1 Buy\n+1 Coin\n+2 <VP>\n`
The `description` field by default is centered. `<br>`, `<n>`, and `\n` will all provide new lines.
- If a Dividers/Tab has more than one card explanation, if space permits, try to mimic a stand alone Dividers/Tab in the overall format. Example from "Settlers - Bustling Village":
`<left><u>Settlers</u>:<n>+1 Card<br>+1 Action<n>Look through your discard pile.
`<left><u>Settlers</u>:<n>+1 Card<br>+1 Action<n>Look through your discard pile.
You may reveal a Copper from it and put it into your hand.<n>
<left><u>Bustling Village</u>:<n><center>+1 Card<br>+3 Actions<n>
Look through your discard pile. You may reveal a Settlers from it and put it into your hand.`

View File

@ -18,4 +18,4 @@
"Villagers",
"<VP>"
]
}
}

View File

@ -47,7 +47,7 @@ For example in English:
"+2 Buys" will be made bold, but
"+1 Action token" will not, since the key word token follows.
Just replace the English terms with the terms used in the target language.
Just replace the English terms with the terms used in the target language.
Generally you should include the singular as well as the plural version of the term.
English versions do not need to be duplicated, since they are used automatically.
The key words "exclude" and "include" MUST NOT BE CHANGED.
@ -135,4 +135,3 @@ Special character sequences are recognized by the program to substitute graphics
- If a Dividers/Tab has more than one card explanation, if space permits, try to mimic a stand alone Dividers/Tab in the overall format.
Example from "Settlers - Bustling Village": "<left><u>Settlers</u>:<n>+1 Card<br>+1 Action<n>Look through your discard pile. You may reveal a Copper from it and put it into your hand.<n><left><u>Bustling Village</u>:<n><center>+1 Card<br>+3 Actions<n>Look through your discard pile. You may reveal a Settlers from it and put it into your hand."

View File

@ -12,7 +12,6 @@ class Card(object):
bonus_regex = None
class CardJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Card):
return obj.__dict__
@ -22,10 +21,26 @@ class Card(object):
def decode_json(obj):
return Card(**obj)
def __init__(self, name=None, cardset='', types=None, cost='', description='',
potcost=0, debtcost=0, extra='', count=-1, card_tag='missing card_tag',
cardset_tags=None, group_tag='', group_top=False, image=None,
text_icon=None, randomizer=True, cardset_tag=''):
def __init__(
self,
name=None,
cardset="",
types=None,
cost="",
description="",
potcost=0,
debtcost=0,
extra="",
count=-1,
card_tag="missing card_tag",
cardset_tags=None,
group_tag="",
group_top=False,
image=None,
text_icon=None,
randomizer=True,
cardset_tag="",
):
if types is None:
types = [] # make sure types is a list
@ -77,7 +92,7 @@ class Card(object):
def getBonusBoldText(self, text):
for regex in Card.bonus_regex:
text = re.sub(regex, '<b>\\1</b>', text)
text = re.sub(regex, "<b>\\1</b>", text)
return text
@staticmethod
@ -91,25 +106,25 @@ class Card(object):
# Make sure have minimum to to anything
if not isinstance(bonus, dict):
return
if 'include' not in bonus:
if "include" not in bonus:
return
if not bonus['include']:
if not bonus["include"]:
return
if 'exclude' not in bonus:
bonus['exclude'] = []
if "exclude" not in bonus:
bonus["exclude"] = []
# Start processing of lists into a single regex statement
# (?i) makes this case insensitive
# (?!\<b\>) and (?!\<\/b\>) prevents matching already bolded items
# (?!\w) prevents smaller word matches. Prevents matching "Action" in "Actions"
if bonus['exclude']:
bonus['exclude'].sort(reverse=True)
exclude_regex = r'(?!\w)(?!\s*(' + '|'.join(bonus['exclude']) + '))'
if bonus["exclude"]:
bonus["exclude"].sort(reverse=True)
exclude_regex = r"(?!\w)(?!\s*(" + "|".join(bonus["exclude"]) + "))"
else:
exclude_regex = ''
exclude_regex = ""
bonus['include'].sort(reverse=True)
include_regex = r"(\+\s*\d+\s*(" + '|'.join(bonus['include']) + "))"
bonus["include"].sort(reverse=True)
include_regex = r"(\+\s*\d+\s*(" + "|".join(bonus["include"]) + "))"
regex = r"(?i)((?!\<b\>)" + include_regex + exclude_regex + r"(?!\<\/b\>))"
Card.bonus_regex.append(regex)
@ -117,23 +132,34 @@ class Card(object):
return '"' + self.name + '"'
def toString(self):
return self.name + ' ' + self.cardset + ' ' + '-'.join(self.types)\
+ ' ' + self.cost + ' ' + self.description + ' ' + self.extra
return (
self.name
+ " "
+ self.cardset
+ " "
+ "-".join(self.types)
+ " "
+ self.cost
+ " "
+ self.description
+ " "
+ self.extra
)
def isType(self, what):
return what in self.getType().getTypeNames()
def isExpansion(self):
return self.isType('Expansion')
return self.isType("Expansion")
def isEvent(self):
return self.isType('Event')
return self.isType("Event")
def isLandmark(self):
return self.isType('Landmark')
return self.isType("Landmark")
def isPrize(self):
return self.isType('Prize')
return self.isType("Prize")
def get_total_cost(self, c):
# Return a tuple that represents the total cost of card c
@ -145,8 +171,8 @@ class Card(object):
if c.isLandmark():
c_cost = 999
elif not c.cost:
c_cost = 0 # if no cost, treat as 0
elif '*' in c.cost:
c_cost = 0 # if no cost, treat as 0
elif "*" in c.cost:
c_cost = 998 # make it a really big number
else:
try:
@ -171,11 +197,15 @@ class Card(object):
setImage = self.image
else:
if self.cardset_tag in Card.sets:
if 'image' in Card.sets[self.cardset_tag]:
setImage = Card.sets[self.cardset_tag]['image']
if "image" in Card.sets[self.cardset_tag]:
setImage = Card.sets[self.cardset_tag]["image"]
if setImage is None and self.cardset_tag != 'base':
print('warning, no set image for set "{}", card "{}"'.format(self.cardset, self.name))
if setImage is None and self.cardset_tag != "base":
print(
'warning, no set image for set "{}", card "{}"'.format(
self.cardset, self.name
)
)
return setImage
def setTextIcon(self):
@ -184,33 +214,42 @@ class Card(object):
setTextIcon = self.text_icon
else:
if self.cardset_tag in Card.sets:
if 'text_icon' in Card.sets[self.cardset_tag]:
setTextIcon = Card.sets[self.cardset_tag]['text_icon']
if "text_icon" in Card.sets[self.cardset_tag]:
setTextIcon = Card.sets[self.cardset_tag]["text_icon"]
if setTextIcon is None and self.cardset != 'base':
print('warning, no set text for set "{}", card "{}"'.format(self.cardset, self.name))
if setTextIcon is None and self.cardset != "base":
print(
'warning, no set text for set "{}", card "{}"'.format(
self.cardset, self.name
)
)
return setTextIcon
def isBlank(self):
return self.isType('Blank')
return self.isType("Blank")
class BlankCard(Card):
def __init__(self, num):
Card.__init__(self, str(num), 'extra', ('Blank',), 0)
Card.__init__(self, str(num), "extra", ("Blank",), 0)
def isBlank(self):
return True
class CardType(object):
@staticmethod
def decode_json(obj):
return CardType(**obj)
def __init__(self, card_type, card_type_image, defaultCardCount=10, tabTextHeightOffset=0, tabCostHeightOffset=-1):
def __init__(
self,
card_type,
card_type_image,
defaultCardCount=10,
tabTextHeightOffset=0,
tabCostHeightOffset=-1,
):
self.typeNames = tuple(card_type)
self.tabImageFile = card_type_image
self.defaultCardCount = defaultCardCount

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 925 KiB

After

Width:  |  Height:  |  Size: 925 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 218 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Some files were not shown because too many files have changed in this diff Show More