- start using argparse instead of optionparser

- make all code conform to pep8 once more
- add a unit test to check for pep8 compliance
- delete old ez_setup
This commit is contained in:
Sumpfork 2016-07-06 15:21:00 -07:00
parent 669fa4c7e6
commit b70bd37d80
11 changed files with 859 additions and 979 deletions

View File

@ -4,6 +4,7 @@ python:
# command to install dependencies # command to install dependencies
install: install:
- pip install -U setuptools - pip install -U setuptools
- pip install -U pycodestyle
- pip install . - pip install .
# command to run tests # command to run tests
script: nosetests script: nosetests

View File

@ -1,33 +1,35 @@
import domdiv import domdiv
from __init__ import __version__ from __init__ import __version__
from zipfile import ZipFile,ZIP_DEFLATED from zipfile import ZipFile, ZIP_DEFLATED
prefix = 'generated/sumpfork_dominion_tabs_' prefix = 'generated/sumpfork_dominion_tabs_'
postfix = 'v' + __version__ + '.pdf' postfix = 'v' + __version__ + '.pdf'
def doit(args,main):
args = args + ' ' + prefix+main+postfix def doit(args, main):
args = args + ' ' + prefix + main + postfix
args = args.split() args = args.split()
fname = args[-1] fname = args[-1]
print ':::Generating ' + fname print ':::Generating ' + fname
domdiv.main(args, '.') domdiv.main(args, '.')
return fname return fname
argsets = [ argsets = [
('',''), ('', ''), ('--orientation=vertical', 'vertical_'),
('--orientation=vertical','vertical_'), ('--papersize=A4', 'A4_'),
('--papersize=A4','A4_'), ('--papersize=A4 --orientation=vertical', 'vertical_A4_'),
('--papersize=A4 --orientation=vertical','vertical_A4_'), ('--size=sleeved', 'sleeved_'),
('--size=sleeved','sleeved_'), ('--size=sleeved --orientation=vertical', 'vertical_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 print fnames
zip = ZipFile('generated/sumpfork_dominion_tabs_v' + __version__ + '.zip','w',ZIP_DEFLATED) zip = ZipFile('generated/sumpfork_dominion_tabs_v' + __version__ + '.zip', 'w',
ZIP_DEFLATED)
for f in fnames: for f in fnames:
zip.write(f) zip.write(f)
zip.close() zip.close()

View File

@ -1,8 +1,8 @@
from optparse import OptionParser
import os import os
import codecs import codecs
import json import json
import sys import sys
import argparse
import reportlab.lib.pagesizes as pagesizes import reportlab.lib.pagesizes as pagesizes
from reportlab.lib.units import cm from reportlab.lib.units import cm
@ -12,7 +12,8 @@ from draw import DividerDrawer
LOCATION_CHOICES = ["tab", "body-top", "hide"] LOCATION_CHOICES = ["tab", "body-top", "hide"]
NAME_ALIGN_CHOICES = ["left", "right", "centre", "edge"] NAME_ALIGN_CHOICES = ["left", "right", "centre", "edge"]
TAB_SIDE_CHOICES = ["left", "right", "left-alternate", "right-alternate", "full"] TAB_SIDE_CHOICES = ["left", "right", "left-alternate", "right-alternate",
"full"]
TEXT_CHOICES = ["card", "rules", "blank"] TEXT_CHOICES = ["card", "rules", "blank"]
@ -21,137 +22,242 @@ def add_opt(options, option, value):
setattr(options, option, value) setattr(options, option, value)
def parse_opts(argstring): def parse_opts(arglist):
parser = OptionParser() parser = argparse.ArgumentParser(description="Generate Dominion Dividers")
parser.add_option("--back_offset", type="float", dest="back_offset", default=0, parser.add_argument('--outfile', default="dominion_dividers.pdf")
help="Points to offset the back page to the right; needed for some printers") parser.add_argument(
parser.add_option("--back_offset_height", type="float", dest="back_offset_height", default=0, "--back_offset",
help="Points to offset the back page upward; needed for some printers") type=float,
parser.add_option("--orientation", type="choice", choices=["horizontal", "vertical"], dest="back_offset",
dest="orientation", default="horizontal", default=0,
help="horizontal or vertical, default:horizontal") help="Points to offset the back page to the right; needed for some printers")
parser.add_option("--sleeved", action="store_true", parser.add_argument(
dest="sleeved", help="use --size=sleeved instead") "--back_offset_height",
parser.add_option("--size", type="string", dest="size", default='normal', type=float,
help="'<%f>x<%f>' (size in cm), or 'normal' = '9.1x5.9', or 'sleeved' = '9.4x6.15'") dest="back_offset_height",
parser.add_option("--minmargin", type="string", dest="minmargin", default="1x1", default=0,
help="'<%f>x<%f>' (size in cm, left/right, top/bottom), default: 1x1") help="Points to offset the back page upward; needed for some printers")
parser.add_option("--papersize", type="string", dest="papersize", default=None, parser.add_argument("--orientation",
help="'<%f>x<%f>' (size in cm), or 'A4', or 'LETTER'") choices=["horizontal", "vertical"],
parser.add_option("--front", type="choice", choices=TEXT_CHOICES, dest="orientation",
dest="text_front", default="card", default="horizontal",
help="Text to print on the front of the divider. choices: card, rules, blank;" help="horizontal or vertical, default:horizontal")
" 'card' will print the text from the game card;" parser.add_argument("--sleeved",
" 'rules' will print additional rules for the game card;" action="store_true",
" 'blank' will not print text on the divider;" dest="sleeved",
" default:card") help="use --size=sleeved instead")
parser.add_option("--back", type="choice", choices=TEXT_CHOICES + ["none"], parser.add_argument(
dest="text_back", default="rules", "--size",
help="Text to print on the back of the divider. choices: card, rules, blank, none;" dest="size",
" 'card' will print the text from the game card;" default='normal',
" 'rules' will print additional rules for the game card;" help="'<%f>x<%f>' (size in cm), or 'normal' = '9.1x5.9', or 'sleeved' = '9.4x6.15'")
" 'blank' will not print text on the divider;" parser.add_argument(
" 'none' will prevent the back pages from printing;" "--minmargin",
" default:rules") dest="minmargin",
parser.add_option("--tab_name_align", type="choice", choices=NAME_ALIGN_CHOICES + ["center"], default="1x1",
dest="tab_name_align", default="left", help="'<%f>x<%f>' (size in cm, left/right, top/bottom), default: 1x1")
help="Alignment of text on the tab. choices: left, right, centre (or center), edge." parser.add_argument("--papersize",
" The edge option will align the card name to the outside edge of the" dest="papersize",
" tab, so that when using tabs on alternating sides," default=None,
" the name is less likely to be hidden by the tab in front" help="'<%f>x<%f>' (size in cm), or 'A4', or 'LETTER'")
" (edge will revert to left when tab_side is full since there is no edge in that case);" parser.add_argument(
" default:left") "--front",
parser.add_option("--tab_side", type="choice", choices=TAB_SIDE_CHOICES, choices=TEXT_CHOICES,
dest="tab_side", default="right-alternate", dest="text_front",
help="Alignment of tab. choices: left, right, left-alternate, right-alternate, full;" default="card",
" left/right forces all tabs to left/right side;" help="Text to print on the front of the divider. choices: card, rules, blank;"
" left-alternate will start on the left and then toggle between left and right for the tabs;" " 'card' will print the text from the game card;"
" right-alternate will start on the right and then toggle between right and left for the tabs;" # noqa " 'rules' will print additional rules for the game card;"
" full will force all label tabs to be full width of the divider" " 'blank' will not print text on the divider;"
" default:right-alternate") " default:card")
parser.add_option("--tabwidth", type="float", default=4, parser.add_argument(
help="width in cm of stick-up tab (ignored if tab_side is full or tabs-only is used)") "--back",
parser.add_option("--cost", action="append", type="choice", choices=TEXT_CHOICES + ["none"],
choices=LOCATION_CHOICES, default=[], dest="text_back",
help="where to display the card cost; may be set to" default="rules",
" 'hide' to indicate it should not be displayed, or" help="Text to print on the back of the divider. choices: card, rules, blank, none;"
" given multiple times to show it in multiple" " 'card' will print the text from the game card;"
" places; valid values are: %s; defaults to 'tab'" " 'rules' will print additional rules for the game card;"
% ", ".join("'%s'" % x for x in LOCATION_CHOICES)) " 'blank' will not print text on the divider;"
parser.add_option("--set_icon", action="append", type="choice", " 'none' will prevent the back pages from printing;"
choices=LOCATION_CHOICES, default=[], " default:rules")
help="where to display the set icon; may be set to" parser.add_argument(
" 'hide' to indicate it should not be displayed, or" "--tab_name_align",
" given multiple times to show it in multiple" choices=NAME_ALIGN_CHOICES + ["center"],
" places; valid values are: %s; defaults to 'tab'" dest="tab_name_align",
% ", ".join("'%s'" % x for x in LOCATION_CHOICES)) default="left",
parser.add_option("--expansions", action="append", type="string", help="Alignment of text on the tab. choices: left, right, centre (or center), edge."
help="subset of dominion expansions to produce tabs for") " The edge option will align the card name to the outside edge of the"
parser.add_option("--cropmarks", action="store_true", dest="cropmarks", " tab, so that when using tabs on alternating sides,"
help="print crop marks on both sides, rather than tab outlines on one") " the name is less likely to be hidden by the tab in front"
parser.add_option("--linewidth", type="float", default=.1, " (edge will revert to left when tab_side is full since there is no edge in that case);"
help="width of lines for card outlines/crop marks") " default:left")
parser.add_option("--write_json", action="store_true", dest="write_json", parser.add_argument(
help="write json version of card definitions and extras") "--tab_side",
parser.add_option("--tabs-only", action="store_true", dest="tabs_only", choices=TAB_SIDE_CHOICES,
help="draw only tabs to be printed on labels, no divider outlines") dest="tab_side",
parser.add_option("--order", type="choice", choices=["expansion", "global", "colour"], dest="order", default="right-alternate",
help="sort order for the cards, whether by expansion or globally alphabetical") help="Alignment of tab. choices: left, right, left-alternate, right-alternate, full;"
parser.add_option("--expansion_dividers", action="store_true", dest="expansion_dividers", " left/right forces all tabs to left/right side;"
help="add dividers describing each expansion set") " left-alternate will start on the left and then toggle between left and right for the tabs;"
parser.add_option("--base_cards_with_expansion", action="store_true", " right-alternate will start on the right and then toggle between right and left for the tabs;" # noqa
help='print the base cards as part of the expansion; ie, a divider for "Silver"' " full will force all label tabs to be full width of the divider"
' will be printed as both a "Dominion" card and as an "Intrigue" card; if this' " default:right-alternate")
' option is not given, all base cards are placed in their own "Base" expansion') parser.add_argument(
parser.add_option("--centre_expansion_dividers", action="store_true", dest="centre_expansion_dividers", "--tabwidth",
help='centre the tabs on expansion dividers') type=float,
parser.add_option("--num_pages", type="int", default=-1, default=4,
help="stop generating after this many pages, -1 for all") help="width in cm of stick-up tab (ignored if tab_side is full or tabs-only is used)")
parser.add_option("--language", default='en_us', help="language of card texts") parser.add_argument("--cost",
parser.add_option("--include_blanks", action="store_true", action="append",
help="include a few dividers with extra text") choices=LOCATION_CHOICES,
parser.add_option("--exclude_events", action="store_true", default=[],
default=False, help="exclude individual dividers for events") help="where to display the card cost; may be set to"
parser.add_option("--exclude_landmarks", action="store_true", " 'hide' to indicate it should not be displayed, or"
default=False, help="exclude individual dividers for landmarks") " given multiple times to show it in multiple"
parser.add_option("--special_card_groups", action="store_true", " places; valid values are: %s; defaults to 'tab'" %
default=False, help="group some cards under special dividers (e.g. Shelters, Prizes)") ", ".join("'%s'" % x for x in LOCATION_CHOICES))
parser.add_option("--exclude_prizes", action="store_true", parser.add_argument("--set_icon",
default=False, help="exclude individual dividers for prizes (cornucopia)") action="append",
parser.add_option("--cardlist", type="string", dest="cardlist", default=None, choices=LOCATION_CHOICES,
help="Path to file that enumerates each card to be printed on its own line.") default=[],
parser.add_option("--no-tab-artwork", action="store_true", dest="no_tab_artwork", help="where to display the set icon; may be set to"
help="don't show background artwork on tabs") " 'hide' to indicate it should not be displayed, or"
parser.add_option("--use-text-set-icon", action="store_true", dest="use_text_set_icon", " given multiple times to show it in multiple"
help="use text/letters to represent a card's set instead of the set icon") " places; valid values are: %s; defaults to 'tab'" %
parser.add_option("--no-page-footer", action="store_true", dest="no_page_footer", ", ".join("'%s'" % x for x in LOCATION_CHOICES))
help="don't print the set name at the bottom of the page.") parser.add_argument(
parser.add_option("--horizontal_gap", type=float, default=0., "--expansions",
help="horizontal gap between dividers in centimeters") action="append",
parser.add_option("--vertical_gap", type=float, default=0., help="subset of dominion expansions to produce tabs for")
help="vertical gap between dividers in centimeters") parser.add_argument(
parser.add_option("--count", action="store_true", dest="count", "--cropmarks",
default=False, help="Display card count on body of the divider.") action="store_true",
parser.add_option("--wrapper", action="store_true", dest="wrapper", dest="cropmarks",
help="Draw wrapper for cards instead of a divider for the cards") help="print crop marks on both sides, rather than tab outlines on one")
parser.add_option("--thickness", type=float, default=2.0, parser.add_argument("--linewidth",
help="Thickness of a stack of 60 cards (Copper) in centimeters." type=float,
" Typically unsleeved cards are 2.0, thin sleeved cards are 2.4, and thick sleeved cards are 3.2." default=.1,
" This is only valid with the --wrapper option." help="width of lines for card outlines/crop marks")
" default:2.0") parser.add_argument(
parser.add_option("--sleeved_thick", action="store_true", "--write_json",
dest="sleeved_thick", help="same as --size=sleeved --thickness 3.2") action="store_true",
parser.add_option("--sleeved_thin", action="store_true", dest="write_json",
dest="sleeved_thin", help="same as --size=sleeved --thickness 2.4") help="write json version of card definitions and extras")
parser.add_option("--notch_length", type=float, default=0.0, parser.add_argument(
help="Length of thumb notch on wrapper in centimeters." "--tabs-only",
" This can make it easier to remove the cards from the wrapper." action="store_true",
" This is only valid with the --wrapper option." dest="tabs_only",
" default:0.0 (i.e., no notch on wrapper)") help="draw only tabs to be printed on labels, no divider outlines")
parser.add_option("--notch", action="store_true", parser.add_argument(
dest="notch", help="same as --notch_length thickness 1.5") "--order",
choices=["expansion", "global", "colour"],
dest="order",
help="sort order for the cards, whether by expansion or globally alphabetical")
parser.add_argument("--expansion_dividers",
action="store_true",
dest="expansion_dividers",
help="add dividers describing each expansion set")
parser.add_argument(
"--base_cards_with_expansion",
action="store_true",
help='print the base cards as part of the expansion; ie, a divider for "Silver"'
' will be printed as both a "Dominion" card and as an "Intrigue" card; if this'
' option is not given, all base cards are placed in their own "Base" expansion')
parser.add_argument("--centre_expansion_dividers",
action="store_true",
dest="centre_expansion_dividers",
help='centre the tabs on expansion dividers')
parser.add_argument(
"--num_pages",
type=int,
default=-1,
help="stop generating after this many pages, -1 for all")
parser.add_argument("--language",
default='en_us',
help="language of card texts")
parser.add_argument("--include_blanks",
action="store_true",
help="include a few dividers with extra text")
parser.add_argument("--exclude_events",
action="store_true",
help="exclude individual dividers for events")
parser.add_argument("--exclude_landmarks",
action="store_true",
help="exclude individual dividers for landmarks")
parser.add_argument(
"--special_card_groups",
action="store_true",
help="group some cards under special dividers (e.g. Shelters, Prizes)")
parser.add_argument(
"--exclude_prizes",
action="store_true",
help="exclude individual dividers for prizes (cornucopia)")
parser.add_argument(
"--cardlist",
dest="cardlist",
help="Path to file that enumerates each card to be printed on its own line.")
parser.add_argument("--no-tab-artwork",
action="store_true",
dest="no_tab_artwork",
help="don't show background artwork on tabs")
parser.add_argument(
"--use-text-set-icon",
action="store_true",
dest="use_text_set_icon",
help="use text/letters to represent a card's set instead of the set icon")
parser.add_argument(
"--no-page-footer",
action="store_true",
dest="no_page_footer",
help="don't print the set name at the bottom of the page.")
parser.add_argument("--horizontal_gap",
type=float,
default=0.,
help="horizontal gap between dividers in centimeters")
parser.add_argument("--vertical_gap",
type=float,
default=0.,
help="vertical gap between dividers in centimeters")
parser.add_argument("--count",
action="store_true",
dest="count",
help="Display card count on body of the divider.")
parser.add_argument(
"--wrapper",
action="store_true",
dest="wrapper",
help="Draw wrapper for cards instead of a divider for the cards")
parser.add_argument(
"--thickness",
type=float,
default=2.0,
help="Thickness of a stack of 60 cards (Copper) in centimeters."
" Typically unsleeved cards are 2.0, thin sleeved cards are 2.4, and thick sleeved cards are 3.2."
" This is only valid with the --wrapper option."
" default:2.0")
parser.add_argument("--sleeved_thick",
action="store_true",
dest="sleeved_thick",
help="same as --size=sleeved --thickness 3.2")
parser.add_argument("--sleeved_thin",
action="store_true",
dest="sleeved_thin",
help="same as --size=sleeved --thickness 2.4")
parser.add_argument(
"--notch_length",
type=float,
default=0.0,
help="Length of thumb notch on wrapper in centimeters."
" This can make it easier to remove the cards from the wrapper."
" This is only valid with the --wrapper option."
" default:0.0 (i.e., no notch on wrapper)")
parser.add_argument("--notch",
action="store_true",
dest="notch",
help="same as --notch_length thickness 1.5")
options, args = parser.parse_args(argstring) options = parser.parse_args(arglist)
if not options.cost: if not options.cost:
options.cost = ['tab'] options.cost = ['tab']
if not options.set_icon: if not options.set_icon:
@ -159,16 +265,16 @@ def parse_opts(argstring):
if options.sleeved_thick: if options.sleeved_thick:
options.thickness = 3.2 options.thickness = 3.2
options.sleeved = True options.sleeved = True
if options.sleeved_thin: if options.sleeved_thin:
options.thickness = 2.4 options.thickness = 2.4
options.sleeved = True options.sleeved = True
if options.notch: if options.notch:
options.notch_length = 1.5 options.notch_length = 1.5
return options, args return options
def parseDimensions(dimensionsStr): def parseDimensions(dimensionsStr):
@ -202,7 +308,8 @@ def parse_papersize(spec):
except AttributeError: except AttributeError:
try: try:
paperwidth, paperheight = parseDimensions(papersize) paperwidth, paperheight = parseDimensions(papersize)
print 'Using custom paper size, %.2fcm x %.2fcm' % (paperwidth / cm, paperheight / cm) print 'Using custom paper size, %.2fcm x %.2fcm' % (
paperwidth / cm, paperheight / cm)
except ValueError: except ValueError:
paperwidth, paperheight = pagesizes.LETTER paperwidth, paperheight = pagesizes.LETTER
return paperwidth, paperheight return paperwidth, paperheight
@ -212,16 +319,16 @@ def parse_cardsize(spec, sleeved):
spec = spec.upper() spec = spec.upper()
if spec == 'SLEEVED' or sleeved: if spec == 'SLEEVED' or sleeved:
dominionCardWidth, dominionCardHeight = (9.4 * cm, 6.15 * cm) dominionCardWidth, dominionCardHeight = (9.4 * cm, 6.15 * cm)
print 'Using sleeved card size, %.2fcm x %.2fcm' % (dominionCardWidth / cm, print 'Using sleeved card size, %.2fcm x %.2fcm' % (
dominionCardHeight / cm) dominionCardWidth / cm, dominionCardHeight / cm)
elif spec in ['NORMAL', 'UNSLEEVED']: elif spec in ['NORMAL', 'UNSLEEVED']:
dominionCardWidth, dominionCardHeight = (9.1 * cm, 5.9 * cm) dominionCardWidth, dominionCardHeight = (9.1 * cm, 5.9 * cm)
print 'Using normal card size, %.2fcm x%.2fcm' % (dominionCardWidth / cm, print 'Using normal card size, %.2fcm x%.2fcm' % (
dominionCardHeight / cm) dominionCardWidth / cm, dominionCardHeight / cm)
else: else:
dominionCardWidth, dominionCardHeight = parseDimensions(spec) dominionCardWidth, dominionCardHeight = parseDimensions(spec)
print 'Using custom card size, %.2fcm x %.2fcm' % (dominionCardWidth / cm, print 'Using custom card size, %.2fcm x %.2fcm' % (
dominionCardHeight / cm) dominionCardWidth / cm, dominionCardHeight / cm)
return dominionCardWidth, dominionCardHeight return dominionCardWidth, dominionCardHeight
@ -250,7 +357,6 @@ def read_write_card_data(options):
class CardSorter(object): class CardSorter(object):
def __init__(self, order, baseCards): def __init__(self, order, baseCards):
self.order = order self.order = order
if order == "global": if order == "global":
@ -280,7 +386,8 @@ class CardSorter(object):
return int(card.isExpansion()), self.baseIndex(card.name), card.name return int(card.isExpansion()), self.baseIndex(card.name), card.name
def by_expansion_sort_key(self, card): def by_expansion_sort_key(self, card):
return card.cardset, int(card.isExpansion()), self.baseIndex(card.name), card.name return card.cardset, int(card.isExpansion()), self.baseIndex(
card.name), card.name
def colour_sort_key(self, card): def colour_sort_key(self, card):
return card.getType().getTypeNames(), card.name return card.getType().getTypeNames(), card.name
@ -291,12 +398,14 @@ class CardSorter(object):
def filter_sort_cards(cards, options): def filter_sort_cards(cards, options):
cardSorter = CardSorter(options.order, cardSorter = CardSorter(
[card.name for card in cards if card.cardset.lower() == 'base']) options.order,
[card.name for card in cards if card.cardset.lower() == 'base'])
if options.base_cards_with_expansion: if options.base_cards_with_expansion:
cards = [card for card in cards if card.cardset.lower() != 'base'] cards = [card for card in cards if card.cardset.lower() != 'base']
else: else:
cards = [card for card in cards if not cardSorter.isBaseExpansionCard(card)] cards = [card for card in cards
if not cardSorter.isBaseExpansionCard(card)]
if options.special_card_groups: if options.special_card_groups:
# Load the card groups file # Load the card groups file
@ -305,24 +414,29 @@ def filter_sort_cards(cards, options):
with codecs.open(card_groups_file, 'r', 'utf-8') as cardgroup_file: with codecs.open(card_groups_file, 'r', 'utf-8') as cardgroup_file:
card_groups = json.load(cardgroup_file) card_groups = json.load(cardgroup_file)
# pull out any cards which are a subcard, and rename the master card # pull out any cards which are a subcard, and rename the master card
new_cards = [] # holds the cards that are to be kept new_cards = [] # holds the cards that are to be kept
all_subcards = [] # holds names of cards that will be removed all_subcards = [] # holds names of cards that will be removed
subcard_parent = {} # holds reverse map of subcard name to group name subcard_parent = {
subcard_count = {} # holds total card count of the subcards for a group } # holds reverse map of subcard name to group name
subcard_count = {
} # holds total card count of the subcards for a group
# Initialize each of the new card groups # Initialize each of the new card groups
for group in card_groups: for group in card_groups:
subcard_count[group] = 0 subcard_count[group] = 0
for subs in card_groups[group]["subcards"]: for subs in card_groups[group]["subcards"]:
all_subcards.append(subs) # add card names to the list for removal all_subcards.append(
subcard_parent[subs] = group # create the reverse mapping of subgroup to group subs) # add card names to the list for removal
subcard_parent[
subs] = group # create the reverse mapping of subgroup to group
# go through the cards and add up the number of subgroup cards # go through the cards and add up the number of subgroup cards
for card in cards: for card in cards:
if card.name in all_subcards: if card.name in all_subcards:
subcard_count[ subcard_parent[card.name] ] += card.getCardCount() subcard_count[subcard_parent[
card.name]] += card.getCardCount()
# fix up the group card holders count & name, and weed out the subgroup cards # fix up the group card holders count & name, and weed out the subgroup cards
for card in cards: for card in cards:
if card.name in card_groups.keys(): if card.name in card_groups.keys():
card.count += subcard_count[card.name] card.count += subcard_count[card.name]
@ -333,21 +447,22 @@ def filter_sort_cards(cards, options):
cards = new_cards cards = new_cards
if options.expansions: if options.expansions:
options.expansions = [o.lower() options.expansions = [o.lower() for o in options.expansions]
for o in options.expansions] reverseMapping = {v: k for k, v in Card.language_mapping.iteritems()}
reverseMapping = {
v: k for k, v in Card.language_mapping.iteritems()}
options.expansions = [ options.expansions = [
reverseMapping.get(e, e) for e in options.expansions] reverseMapping.get(e, e) for e in options.expansions
]
filteredCards = [] filteredCards = []
knownExpansions = set() knownExpansions = set()
for c in cards: for c in cards:
knownExpansions.add(c.cardset) knownExpansions.add(c.cardset)
if next((e for e in options.expansions if c.cardset.startswith(e)), None): if next((e for e in options.expansions
if c.cardset.startswith(e)), None):
filteredCards.append(c) filteredCards.append(c)
unknownExpansions = set(options.expansions) - knownExpansions unknownExpansions = set(options.expansions) - knownExpansions
if unknownExpansions: if unknownExpansions:
print "Error - unknown expansion(s): %s" % ", ".join(unknownExpansions) print "Error - unknown expansion(s): %s" % ", ".join(
unknownExpansions)
cards = filteredCards cards = filteredCards
@ -399,8 +514,6 @@ def filter_sort_cards(cards, options):
holder.setCardCount(count) holder.setCardCount(count)
cards = filteredCards cards = filteredCards
if options.cardlist: if options.cardlist:
cardlist = set() cardlist = set()
with open(options.cardlist) as cardfile: with open(options.cardlist) as cardfile:
@ -414,11 +527,14 @@ def filter_sort_cards(cards, options):
for c in cards: for c in cards:
if cardSorter.isBaseExpansionCard(c): if cardSorter.isBaseExpansionCard(c):
continue continue
cardnamesByExpansion.setdefault( cardnamesByExpansion.setdefault(c.cardset,
c.cardset, []).append(c.name.strip()) []).append(c.name.strip())
for exp, names in cardnamesByExpansion.iteritems(): for exp, names in cardnamesByExpansion.iteritems():
c = Card( c = Card(exp,
exp, exp, ("Expansion",), None, ' | '.join(sorted(names)), count=len(names)) exp, ("Expansion", ),
None,
' | '.join(sorted(names)),
count=len(names))
cards.append(c) cards.append(c)
cards.sort(key=cardSorter) cards.sort(key=cardSorter)
@ -428,7 +544,8 @@ def filter_sort_cards(cards, options):
def calculate_layout(options, cards=[]): def calculate_layout(options, cards=[]):
dominionCardWidth, dominionCardHeight = parse_cardsize(options.size, options.sleeved) dominionCardWidth, dominionCardHeight = parse_cardsize(options.size,
options.sleeved)
paperwidth, paperheight = parse_papersize(options.papersize) paperwidth, paperheight = parse_papersize(options.papersize)
if options.orientation == "vertical": if options.orientation == "vertical":
@ -441,24 +558,23 @@ def calculate_layout(options, cards=[]):
if options.tab_side == "full" and options.tab_name_align == "edge": if options.tab_side == "full" and options.tab_name_align == "edge":
# This case does not make sense since there are two tab edges in this case. So picking left edge. # This case does not make sense since there are two tab edges in this case. So picking left edge.
print >>sys.stderr, "** Warning: Aligning card name as 'left' for 'full' tabs **" print >> sys.stderr, "** Warning: Aligning card name as 'left' for 'full' tabs **"
options.tab_name_align = "left" options.tab_name_align = "left"
fixedMargins = False fixedMargins = False
if options.tabs_only: if options.tabs_only:
# fixed for Avery 8867 for now # fixed for Avery 8867 for now
minmarginwidth = 0.86 * cm # was 0.76 minmarginwidth = 0.86 * cm # was 0.76
minmarginheight = 1.37 * cm # was 1.27 minmarginheight = 1.37 * cm # was 1.27
labelHeight = 1.07 * cm # was 1.27 labelHeight = 1.07 * cm # was 1.27
labelWidth = 4.24 * cm # was 4.44 labelWidth = 4.24 * cm # was 4.44
horizontalBorderSpace = 0.96 * cm # was 0.76 horizontalBorderSpace = 0.96 * cm # was 0.76
verticalBorderSpace = 0.20 * cm # was 0.01 verticalBorderSpace = 0.20 * cm # was 0.01
dividerBaseHeight = 0 dividerBaseHeight = 0
dividerWidth = labelWidth dividerWidth = labelWidth
fixedMargins = True fixedMargins = True
else: else:
minmarginwidth, minmarginheight = parseDimensions( minmarginwidth, minmarginheight = parseDimensions(options.minmargin)
options.minmargin)
if options.tab_side == "full": if options.tab_side == "full":
labelWidth = dividerWidth labelWidth = dividerWidth
else: else:
@ -469,17 +585,19 @@ def calculate_layout(options, cards=[]):
dividerHeight = dividerBaseHeight + labelHeight dividerHeight = dividerBaseHeight + labelHeight
dividerWidthReserved = dividerWidth + horizontalBorderSpace dividerWidthReserved = dividerWidth + horizontalBorderSpace
dividerHeightReserved = dividerHeight + verticalBorderSpace dividerHeightReserved = dividerHeight + verticalBorderSpace
if options.wrapper: if options.wrapper:
max_card_stack_height = max(c.getStackHeight(options.thickness) for c in cards) max_card_stack_height = max(c.getStackHeight(options.thickness)
dividerHeightReserved = (dividerHeightReserved * 2) + (max_card_stack_height * 2) for c in cards)
dividerHeightReserved = (dividerHeightReserved * 2) + (
max_card_stack_height * 2)
print "Max Card Stack Height: {:.2f}cm ".format(max_card_stack_height) print "Max Card Stack Height: {:.2f}cm ".format(max_card_stack_height)
# Notch measurements # Notch measurements
notch_height = 0.25 * cm # thumb notch height notch_height = 0.25 * cm # thumb notch height
notch_width1 = options.notch_length * cm # thumb notch width: top away from tab notch_width1 = options.notch_length * cm # thumb notch width: top away from tab
notch_width2 = 0.00 * cm # thumb notch width: bottom on side of tab notch_width2 = 0.00 * cm # thumb notch width: bottom on side of tab
add_opt(options, 'dividerWidth', dividerWidth) add_opt(options, 'dividerWidth', dividerWidth)
add_opt(options, 'dividerHeight', dividerHeight) add_opt(options, 'dividerHeight', dividerHeight)
@ -495,16 +613,20 @@ def calculate_layout(options, cards=[]):
# as we don't draw anything in the final border, it shouldn't count towards how many tabs we can fit # as we don't draw anything in the final border, it shouldn't count towards how many tabs we can fit
# so it gets added back in to the page size here # so it gets added back in to the page size here
numDividersVerticalP = int( numDividersVerticalP = int(
(paperheight - 2 * minmarginheight + verticalBorderSpace) / options.dividerHeightReserved) (paperheight - 2 * minmarginheight + verticalBorderSpace) /
options.dividerHeightReserved)
numDividersHorizontalP = int( numDividersHorizontalP = int(
(paperwidth - 2 * minmarginwidth + horizontalBorderSpace) / options.dividerWidthReserved) (paperwidth - 2 * minmarginwidth + horizontalBorderSpace) /
options.dividerWidthReserved)
numDividersVerticalL = int( numDividersVerticalL = int(
(paperwidth - 2 * minmarginwidth + verticalBorderSpace) / options.dividerHeightReserved) (paperwidth - 2 * minmarginwidth + verticalBorderSpace) /
options.dividerHeightReserved)
numDividersHorizontalL = int( numDividersHorizontalL = int(
(paperheight - 2 * minmarginheight + horizontalBorderSpace) / options.dividerWidthReserved) (paperheight - 2 * minmarginheight + horizontalBorderSpace) /
options.dividerWidthReserved)
if ((numDividersVerticalL * numDividersHorizontalL > if ((numDividersVerticalL * numDividersHorizontalL > numDividersVerticalP *
numDividersVerticalP * numDividersHorizontalP) and not fixedMargins): numDividersHorizontalP) and not fixedMargins):
add_opt(options, 'numDividersVertical', numDividersVerticalL) add_opt(options, 'numDividersVertical', numDividersVerticalL)
add_opt(options, 'numDividersHorizontal', numDividersHorizontalL) add_opt(options, 'numDividersHorizontal', numDividersHorizontalL)
add_opt(options, 'paperheight', paperwidth) add_opt(options, 'paperheight', paperwidth)
@ -522,17 +644,17 @@ def calculate_layout(options, cards=[]):
if not fixedMargins: if not fixedMargins:
# dynamically max margins # dynamically max margins
add_opt(options, 'horizontalMargin', add_opt(options, 'horizontalMargin',
(options.paperwidth - (options.paperwidth - options.numDividersHorizontal *
options.numDividersHorizontal * options.dividerWidthReserved + horizontalBorderSpace) / 2) options.dividerWidthReserved + horizontalBorderSpace) / 2)
add_opt(options, 'verticalMargin', add_opt(options, 'verticalMargin',
(options.paperheight - (options.paperheight - options.numDividersVertical *
options.numDividersVertical * options.dividerHeightReserved + verticalBorderSpace) / 2) options.dividerHeightReserved + verticalBorderSpace) / 2)
else: else:
add_opt(options, 'horizontalMargin', minmarginwidth) add_opt(options, 'horizontalMargin', minmarginwidth)
add_opt(options, 'verticalMargin', minmarginheight) add_opt(options, 'verticalMargin', minmarginheight)
def generate(options, data_path, f): def generate(options, data_path):
add_opt(options, 'data_path', data_path) add_opt(options, 'data_path', data_path)
@ -543,26 +665,19 @@ def generate(options, data_path, f):
calculate_layout(options, cards) calculate_layout(options, cards)
print "Paper dimensions: {:.2f}cm (w) x {:.2f}cm (h)".format(options.paperwidth / cm, print "Paper dimensions: {:.2f}cm (w) x {:.2f}cm (h)".format(
options.paperheight / cm) options.paperwidth / cm, options.paperheight / cm)
print "Tab dimensions: {:.2f}cm (w) x {:.2f}cm (h)".format(options.dividerWidthReserved / cm, print "Tab dimensions: {:.2f}cm (w) x {:.2f}cm (h)".format(
options.dividerHeightReserved / cm) options.dividerWidthReserved / cm, options.dividerHeightReserved / cm)
print '{} dividers horizontally, {} vertically'.format(options.numDividersHorizontal, print '{} dividers horizontally, {} vertically'.format(
options.numDividersVertical) options.numDividersHorizontal, options.numDividersVertical)
print "Margins: {:.2f}cm h, {:.2f}cm v\n".format(options.horizontalMargin / cm, print "Margins: {:.2f}cm h, {:.2f}cm v\n".format(
options.verticalMargin / cm) options.horizontalMargin / cm, options.verticalMargin / cm)
if not f:
f = "dominion_dividers.pdf"
dd = DividerDrawer() dd = DividerDrawer()
dd.draw(f, cards, options) dd.draw(cards, options)
def main(argstring, data_path): def main(arglist, data_path):
options, args = parse_opts(argstring) options = parse_opts(arglist)
fname = None return generate(options, data_path)
if args:
fname = args[0]
return generate(options, data_path, fname)

View File

@ -2,6 +2,7 @@ import json
import os import os
from reportlab.lib.units import cm from reportlab.lib.units import cm
def getType(typespec): def getType(typespec):
return cardTypes[tuple(typespec)] return cardTypes[tuple(typespec)]
@ -101,7 +102,6 @@ class Card(object):
return promoTextIcons[cardName.lower()] return promoTextIcons[cardName.lower()]
return None return None
def __init__(self, name, cardset, types, cost, description='', potcost=0, debtcost=0, extra='', count=-1): def __init__(self, name, cardset, types, cost, description='', potcost=0, debtcost=0, extra='', count=-1):
self.name = name.strip() self.name = name.strip()
self.cardset = cardset.strip() self.cardset = cardset.strip()
@ -151,7 +151,6 @@ class Card(object):
def isType(self, what): def isType(self, what):
return what in self.getType().getTypeNames() return what in self.getType().getTypeNames()
def setImage(self): def setImage(self):
setImage = Card.getSetImage(self.cardset, self.name) setImage = Card.getSetImage(self.cardset, self.name)
if setImage is None and self.cardset not in ['base', 'extra'] and not self.isExpansion(): if setImage is None and self.cardset not in ['base', 'extra'] and not self.isExpansion():
@ -215,47 +214,47 @@ class CardType(object):
cardTypes = [ cardTypes = [
CardType(('Action',), 'action.png'), CardType(('Action',), 'action.png'),
CardType(('Action', 'Attack'), 'action.png'), CardType(('Action', 'Attack'), 'action.png'),
CardType(('Action', 'Attack', 'Prize'), 'action.png',1), CardType(('Action', 'Attack', 'Prize'), 'action.png', 1),
CardType(('Action', 'Reaction'), 'reaction.png'), CardType(('Action', 'Reaction'), 'reaction.png'),
CardType(('Action', 'Victory'), 'action-victory.png',12), CardType(('Action', 'Victory'), 'action-victory.png', 12),
CardType(('Action', 'Duration'), 'duration.png',5), CardType(('Action', 'Duration'), 'duration.png', 5),
CardType(('Action', 'Duration', 'Reaction'), 'duration-reaction.png'), CardType(('Action', 'Duration', 'Reaction'), 'duration-reaction.png'),
CardType(('Action', 'Attack', 'Duration'), 'duration.png'), CardType(('Action', 'Attack', 'Duration'), 'duration.png'),
CardType(('Action', 'Looter'), 'action.png'), CardType(('Action', 'Looter'), 'action.png'),
CardType(('Action', 'Prize'), 'action.png',1), CardType(('Action', 'Prize'), 'action.png', 1),
CardType(('Action', 'Ruins'), 'ruins.png',10, 0, 1), CardType(('Action', 'Ruins'), 'ruins.png', 10, 0, 1),
CardType(('Action', 'Shelter'), 'action-shelter.png',6), CardType(('Action', 'Shelter'), 'action-shelter.png', 6),
CardType(('Action', 'Attack', 'Duration'), 'duration.png'), CardType(('Action', 'Attack', 'Duration'), 'duration.png'),
CardType(('Action', 'Attack', 'Looter'), 'action.png'), CardType(('Action', 'Attack', 'Looter'), 'action.png'),
CardType(('Action', 'Attack', 'Traveller'), 'action.png',5), CardType(('Action', 'Attack', 'Traveller'), 'action.png', 5),
CardType(('Action', 'Reserve'), 'reserve.png',5), CardType(('Action', 'Reserve'), 'reserve.png', 5),
CardType(('Action', 'Reserve', 'Victory'), 'reserve-victory.png',12), CardType(('Action', 'Reserve', 'Victory'), 'reserve-victory.png', 12),
CardType(('Action', 'Traveller'), 'action.png',5), CardType(('Action', 'Traveller'), 'action.png', 5),
CardType(('Action', 'Gathering'), 'action.png'), CardType(('Action', 'Gathering'), 'action.png'),
CardType(('Action', 'Treasure'), 'action-treasure.png'), CardType(('Action', 'Treasure'), 'action-treasure.png'),
CardType(('Prize',), 'action.png',1), CardType(('Prize',), 'action.png', 1),
CardType(('Event',), 'event.png',1), CardType(('Event',), 'event.png', 1),
CardType(('Reaction',), 'reaction.png'), CardType(('Reaction',), 'reaction.png'),
CardType(('Reaction', 'Shelter'), 'reaction-shelter.png',6), CardType(('Reaction', 'Shelter'), 'reaction-shelter.png', 6),
CardType(('Treasure',), 'treasure.png',10, 3, 0), CardType(('Treasure',), 'treasure.png', 10, 3, 0),
CardType(('Treasure', 'Attack'), 'treasure.png'), CardType(('Treasure', 'Attack'), 'treasure.png'),
CardType(('Treasure', 'Victory'), 'treasure-victory.png',12), CardType(('Treasure', 'Victory'), 'treasure-victory.png', 12),
CardType(('Treasure', 'Prize'), 'treasure.png',1, 3, 0), CardType(('Treasure', 'Prize'), 'treasure.png', 1, 3, 0),
CardType(('Treasure', 'Reaction'), 'treasure-reaction.png',10, 0, 1), CardType(('Treasure', 'Reaction'), 'treasure-reaction.png', 10, 0, 1),
CardType(('Treasure', 'Reserve'), 'reserve-treasure.png'), CardType(('Treasure', 'Reserve'), 'reserve-treasure.png'),
CardType(('Victory',), 'victory.png',12), CardType(('Victory',), 'victory.png', 12),
CardType(('Victory', 'Reaction'), 'victory-reaction.png',12, 0, 1), CardType(('Victory', 'Reaction'), 'victory-reaction.png', 12, 0, 1),
CardType(('Victory', 'Shelter'), 'victory-shelter.png',6), CardType(('Victory', 'Shelter'), 'victory-shelter.png', 6),
CardType(('Victory', 'Castle'), 'victory.png',12), CardType(('Victory', 'Castle'), 'victory.png', 12),
CardType(('Curse',), 'curse.png', 30, 3), CardType(('Curse',), 'curse.png', 30, 3),
CardType(('Trash',), 'action.png', 1), CardType(('Trash',), 'action.png', 1),
CardType(('Prizes',), 'action.png',0), CardType(('Prizes',), 'action.png', 0),
CardType(('Events',), 'event.png',0), CardType(('Events',), 'event.png', 0),
CardType(('Shelters',), 'shelter.png',0), CardType(('Shelters',), 'shelter.png', 0),
CardType(('Expansion',), 'expansion.png',0, 4), CardType(('Expansion',), 'expansion.png', 0, 4),
CardType(('Blank',), ''), CardType(('Blank',), ''),
CardType(('Landmark',), 'landmark.png',1), CardType(('Landmark',), 'landmark.png', 1),
CardType(('Landmarks',), 'landmark.png',0) CardType(('Landmarks',), 'landmark.png', 0)
] ]
cardTypes = dict(((c.getTypeNames(), c) for c in cardTypes)) cardTypes = dict(((c.getTypeNames(), c) for c in cardTypes))

View File

@ -20,7 +20,6 @@ def split(l, n):
class DividerDrawer(object): class DividerDrawer(object):
def __init__(self): def __init__(self):
self.odd = True self.odd = True
self.canvas = None self.canvas = None
@ -29,32 +28,32 @@ class DividerDrawer(object):
try: try:
dirn = os.path.join(self.options.data_path, 'fonts') dirn = os.path.join(self.options.data_path, 'fonts')
self.fontNameRegular = 'MinionPro-Regular' self.fontNameRegular = 'MinionPro-Regular'
pdfmetrics.registerFont( pdfmetrics.registerFont(TTFont(self.fontNameRegular, os.path.join(
TTFont(self.fontNameRegular, os.path.join(dirn, 'MinionPro-Regular.ttf'))) dirn, 'MinionPro-Regular.ttf')))
self.fontNameBold = 'MinionPro-Bold' self.fontNameBold = 'MinionPro-Bold'
pdfmetrics.registerFont( pdfmetrics.registerFont(TTFont(self.fontNameBold, os.path.join(
TTFont(self.fontNameBold, os.path.join(dirn, 'MinionPro-Bold.ttf'))) dirn, 'MinionPro-Bold.ttf')))
self.fontNameOblique = 'MinionPro-Oblique' self.fontNameOblique = 'MinionPro-Oblique'
pdfmetrics.registerFont( pdfmetrics.registerFont(TTFont(self.fontNameOblique, os.path.join(
TTFont(self.fontNameOblique, os.path.join(dirn, 'MinionPro-It.ttf'))) dirn, 'MinionPro-It.ttf')))
except: except:
print >>sys.stderr, "Warning, Minion Pro Font ttf file not found! Falling back on Times" print >> sys.stderr, "Warning, Minion Pro Font ttf file not found! Falling back on Times"
self.fontNameRegular = 'Times-Roman' self.fontNameRegular = 'Times-Roman'
self.fontNameBold = 'Times-Bold' self.fontNameBold = 'Times-Bold'
self.fontNameOblique = 'Times-Oblique' self.fontNameOblique = 'Times-Oblique'
def getOutline(self, card, isExpansionDivider = False): def getOutline(self, card, isExpansionDivider=False):
dividerWidth = self.options.dividerWidth dividerWidth = self.options.dividerWidth
dividerHeight = self.options.dividerHeight dividerHeight = self.options.dividerHeight
dividerBaseHeight = self.options.dividerBaseHeight dividerBaseHeight = self.options.dividerBaseHeight
tabLabelWidth = self.options.labelWidth tabLabelWidth = self.options.labelWidth
notch_height = self.options.notch_height # thumb notch height notch_height = self.options.notch_height # thumb notch height
notch_width1 = self.options.notch_width1 # thumb notch width: top away from tab notch_width1 = self.options.notch_width1 # thumb notch width: top away from tab
notch_width2 = self.options.notch_width2 # thumb notch width: bottom on side of tab notch_width2 = self.options.notch_width2 # thumb notch width: bottom on side of tab
theTabHeight = dividerHeight - dividerBaseHeight theTabHeight = dividerHeight - dividerBaseHeight
theTabWidth = self.options.labelWidth theTabWidth = self.options.labelWidth
if isExpansionDivider: if isExpansionDivider:
side_2_tab = (dividerWidth - theTabWidth) / 2 side_2_tab = (dividerWidth - theTabWidth) / 2
@ -64,15 +63,15 @@ class DividerDrawer(object):
nonTabWidth = dividerWidth - tabLabelWidth - side_2_tab nonTabWidth = dividerWidth - tabLabelWidth - side_2_tab
def DeltaXYtoLines(delta): def DeltaXYtoLines(delta):
result = [] result = []
started = False started = False
for x,y in delta: for x, y in delta:
if not started: if not started:
last_x = x last_x = x
last_y = y last_y = y
started = True started = True
else: else:
result.append( (last_x , last_y, last_x + x, last_y + y) ) result.append((last_x, last_y, last_x + x, last_y + y))
last_x = last_x + x last_x = last_x + x
last_y = last_y + y last_y = last_y + y
return result return result
@ -90,21 +89,21 @@ class DividerDrawer(object):
# | | # | |
# A+-------------------------------------------------+B # A+-------------------------------------------------+B
# delta x delta y # delta x delta y
delta = [ ( 0 , 0 ), # to A delta = [(0, 0), # to A
( dividerWidth , 0 ), #A to B (dividerWidth, 0), # A to B
( 0 , dividerBaseHeight ), #B to C (0, dividerBaseHeight), # B to C
( -side_2_tab , 0 ), #C to D (-side_2_tab, 0), # C to D
( 0 , theTabHeight ), #D to E (0, theTabHeight), # D to E
( -theTabWidth , 0 ), #E to F (-theTabWidth, 0), # E to F
( 0 , -theTabHeight ), #F to G (0, -theTabHeight), # F to G
( -nonTabWidth , 0 ), #G to H (-nonTabWidth, 0), # G to H
( 0 , -dividerBaseHeight )] #H to A (0, -dividerBaseHeight)] # H to A
self.canvas.lines(DeltaXYtoLines(delta)) self.canvas.lines(DeltaXYtoLines(delta))
else: else:
# Card Wrapper Outline # Card Wrapper Outline
notch_width3 = notch_width1 # thumb notch width: bottom away from tab notch_width3 = notch_width1 # thumb notch width: bottom away from tab
stackHeight = card.getStackHeight(self.options.thickness) stackHeight = card.getStackHeight(self.options.thickness)
body_minus_notches = dividerBaseHeight - (2.0 * notch_height) body_minus_notches = dividerBaseHeight - (2.0 * notch_height)
tab_2_notch = dividerWidth - theTabWidth - side_2_tab - notch_width1 tab_2_notch = dividerWidth - theTabWidth - side_2_tab - notch_width1
if (tab_2_notch < 0): if (tab_2_notch < 0):
@ -139,85 +138,101 @@ class DividerDrawer(object):
# + E+-------------------+F + # + E+-------------------+F +
# #
# delta x delta y # delta x delta y
delta = [ ( 0 , theTabHeight+notch_height), # to A delta = [(0, theTabHeight + notch_height), # to A
( notch_width1, 0 ), #A to B (notch_width1, 0), # A to B
( 0 , -notch_height ), #B to C (0, -notch_height), # B to C
( tab_2_notch , 0 ), #C to D (tab_2_notch, 0), # C to D
( 0 , -theTabHeight ), #D to E (0, -theTabHeight), # D to E
( theTabWidth , 0 ), #E to F (theTabWidth, 0), # E to F
( 0 , theTabHeight ), #F to G (0, theTabHeight), # F to G
( side_2_tab , 0 ), #G to H (side_2_tab, 0), # G to H
( 0 , notch_height ), #H to I (0, notch_height), # H to I
( 0 , body_minus_notches ), #I to J (0, body_minus_notches), # I to J
(-notch_width2, 0 ), #J to K (-notch_width2, 0), # J to K
( 0 , notch_height ), #K to L (0, notch_height), # K to L
( 0 , stackHeight ), #L to M (0, stackHeight), # L to M
( 0 , notch_height ), #M to N (0, notch_height), # M to N
( notch_width2, 0 ), #N to O (notch_width2, 0), # N to O
( 0 , body_minus_notches ), #O to P (0, body_minus_notches), # O to P
( 0 , notch_height ), #P to Q (0, notch_height), # P to Q
(-side_2_tab , 0 ), #Q to R (-side_2_tab, 0), # Q to R
( 0 , stackHeight ), #R to S (0, stackHeight), # R to S
( 0 , theTabHeight ), #S to T (0, theTabHeight), # S to T
(-theTabWidth , 0 ), #T to U (-theTabWidth, 0), # T to U
( 0 , -theTabHeight ), #U to V (0, -theTabHeight), # U to V
( 0 , -stackHeight ), #V to W (0, -stackHeight), # V to W
(-tab_2_notch , 0 ), #W to X (-tab_2_notch, 0), # W to X
( 0 , -notch_height ), #X to Y (0, -notch_height), # X to Y
(-notch_width1, 0 ), #Y to Z (-notch_width1, 0), # Y to Z
( 0 , -body_minus_notches ), #Z to AA (0, -body_minus_notches), # Z to AA
( notch_width3, 0 ), #AA to BB (notch_width3, 0), # AA to BB
( 0 , -notch_height ), #BB to CC (0, -notch_height), # BB to CC
( 0 , -stackHeight ), #CC to DD (0, -stackHeight), # CC to DD
( 0 , -notch_height ), #DD to EE (0, -notch_height), # DD to EE
(-notch_width3, 0 ), #EE to FF (-notch_width3, 0), # EE to FF
( 0 , -body_minus_notches )] #FF to A (0, -body_minus_notches)] # FF to A
self.canvas.lines(DeltaXYtoLines(delta)) self.canvas.lines(DeltaXYtoLines(delta))
self.canvas.setStrokeGray(0.9) self.canvas.setStrokeGray(0.9)
self.canvas.line(dividerWidth-side_2_tab, dividerHeight + dividerBaseHeight + stackHeight , dividerWidth-side_2_tab-theTabWidth , dividerHeight + dividerBaseHeight + stackHeight ) self.canvas.line(dividerWidth - side_2_tab,
self.canvas.line(dividerWidth-side_2_tab, dividerHeight + dividerBaseHeight + 2*stackHeight , dividerWidth-side_2_tab-theTabWidth , dividerHeight + dividerBaseHeight + 2*stackHeight ) dividerHeight + dividerBaseHeight + stackHeight,
self.canvas.line(notch_width1 , dividerHeight , dividerWidth - notch_width2, dividerHeight ) dividerWidth - side_2_tab - theTabWidth,
self.canvas.line(notch_width1 , dividerHeight + stackHeight , dividerWidth - notch_width2, dividerHeight + stackHeight ) dividerHeight + dividerBaseHeight + stackHeight)
self.canvas.line(
dividerWidth - side_2_tab, dividerHeight + dividerBaseHeight +
2 * stackHeight, dividerWidth - side_2_tab - theTabWidth,
dividerHeight + dividerBaseHeight + 2 * stackHeight)
self.canvas.line(notch_width1, dividerHeight,
dividerWidth - notch_width2, dividerHeight)
self.canvas.line(notch_width1, dividerHeight + stackHeight,
dividerWidth - notch_width2,
dividerHeight + stackHeight)
self.canvas.restoreState() self.canvas.restoreState()
def draw(self, fname, cards, options): def draw(self, cards, options):
self.options = options self.options = options
self.registerFonts() self.registerFonts()
self.canvas = canvas.Canvas( self.canvas = canvas.Canvas(
fname, pagesize=(options.paperwidth, options.paperheight)) options.outfile,
pagesize=(options.paperwidth, options.paperheight))
self.drawDividers(cards) self.drawDividers(cards)
self.canvas.save() self.canvas.save()
def add_inline_images(self, text, fontsize): def add_inline_images(self, text, fontsize):
path = os.path.join(self.options.data_path, 'images') path = os.path.join(self.options.data_path, 'images')
replace = '<img src='"'%s/coin_small_\\1.png'"' width=%d height='"'100%%'"' valign='"'middle'"'/>' % ( replace = '<img src=' "'%s/coin_small_\\1.png'" ' width=%d height=' "'100%%'" ' valign=' "'middle'" '/>'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('(\d+)\s(c|C)oin(s)?', replace, text) text = re.sub('(\d+)\s(c|C)oin(s)?', replace, text)
replace = '<img src='"'%s/coin_small_question.png'"' width=%d height='"'100%%'"' valign='"'middle'"'/>' % ( replace = '<img src=' "'%s/coin_small_question.png'" ' width=%d height=' "'100%%'" ' valign=' "'middle'" '/>'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('\?\s(c|C)oin(s)?', replace, text) text = re.sub('\?\s(c|C)oin(s)?', replace, text)
replace = '<img src='"'%s/coin_small_empty.png'"' width=%d height='"'100%%'"' valign='"'middle'"'/>' % ( replace = '<img src=' "'%s/coin_small_empty.png'" ' width=%d height=' "'100%%'" ' valign=' "'middle'" '/>'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('empty\s(c|C)oin(s)?', replace, text) text = re.sub('empty\s(c|C)oin(s)?', replace, text)
replace = '<img src='"'%s/victory_emblem.png'"' width=%d height='"'120%%'"' valign='"'middle'"'/>' % ( replace = '<img src=' "'%s/victory_emblem.png'" ' width=%d height=' "'120%%'" ' valign=' "'middle'" '/>'
path, fontsize * 1.5) replace = replace % (path, fontsize * 1.5)
text = re.sub('\<VP\>', replace, text) text = re.sub('\<VP\>', replace, text)
replace = '<img src='"'%s/debt_\\1.png'"' width=%d height='"'105%%'"' valign='"'middle'"'/>&thinsp;' % ( replace = '<img src=' "'%s/debt_\\1.png'" ' width=%d height=' "'105%%'" ' valign=' "'middle'" '/>&thinsp;'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('(\d+)\sDebt', replace, text) text = re.sub('(\d+)\sDebt', replace, text)
replace = '<img src='"'%s/debt.png'"' width=%d height='"'105%%'"' valign='"'middle'"'/>&thinsp;' % ( replace = '<img src=' "'%s/debt.png'" ' width=%d height=' "'105%%'" ' valign=' "'middle'" '/>&thinsp;'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('Debt', replace, text) text = re.sub('Debt', replace, text)
replace = '<img src='"'%s/potion_small.png'"' width=%d height='"'100%%'"' valign='"'middle'"'/>' % ( replace = '<img src=' "'%s/potion_small.png'" ' width=%d height=' "'100%%'" ' valign=' "'middle'" '/>'
path, fontsize * 1.2) replace = replace % (path, fontsize * 1.2)
text = re.sub('Potion', replace, text) text = re.sub('Potion', replace, text)
return text return text
def drawOutline(self, card, x, y, rightSide, isBack=False, isExpansionDivider=False): def drawOutline(self,
card,
x,
y,
rightSide,
isBack=False,
isExpansionDivider=False):
# draw outline or cropmarks # draw outline or cropmarks
self.canvas.saveState() self.canvas.saveState()
self.canvas.setLineWidth(self.options.linewidth) self.canvas.setLineWidth(self.options.linewidth)
@ -245,11 +260,11 @@ class DividerDrawer(object):
self.canvas.scale(-1, 1) self.canvas.scale(-1, 1)
if cropmarksleft or cropmarksright: if cropmarksleft or cropmarksright:
self.canvas.line(-2 * cmw, 0, -cmw, 0) self.canvas.line(-2 * cmw, 0, -cmw, 0)
self.canvas.line(-2 * cmw, self.canvas.line(-2 * cmw, self.options.dividerBaseHeight,
self.options.dividerBaseHeight, -cmw, self.options.dividerBaseHeight) -cmw, self.options.dividerBaseHeight)
if y > 0: if y > 0:
self.canvas.line(-2 * cmw, self.canvas.line(-2 * cmw, self.options.dividerHeight,
self.options.dividerHeight, -cmw, self.options.dividerHeight) -cmw, self.options.dividerHeight)
if mirror: if mirror:
self.canvas.restoreState() self.canvas.restoreState()
@ -275,12 +290,15 @@ class DividerDrawer(object):
self.canvas.line(leftLine, -2 * cmw, leftLine, -cmw) self.canvas.line(leftLine, -2 * cmw, leftLine, -cmw)
if y == self.options.numDividersVertical - 1: if y == self.options.numDividersVertical - 1:
self.canvas.line(rightLine, self.options.dividerHeight + cmw, self.canvas.line(rightLine, self.options.dividerHeight + cmw,
rightLine, self.options.dividerHeight + 2 * cmw) rightLine,
self.options.dividerHeight + 2 * cmw)
self.canvas.line(middleLine, self.options.dividerHeight + cmw, self.canvas.line(middleLine, self.options.dividerHeight + cmw,
middleLine, self.options.dividerHeight + 2 * cmw) middleLine,
self.options.dividerHeight + 2 * cmw)
if cropmarksleft: if cropmarksleft:
self.canvas.line(leftLine, self.options.dividerHeight + cmw, self.canvas.line(
leftLine, self.options.dividerHeight + 2 * cmw) leftLine, self.options.dividerHeight + cmw, leftLine,
self.options.dividerHeight + 2 * cmw)
self.canvas.restoreState() self.canvas.restoreState()
@ -288,14 +306,20 @@ class DividerDrawer(object):
if card.count < 1: if card.count < 1:
return 0 return 0
# base width is 16 (for image) + 2 (1 pt border on each side) # base width is 16 (for image) + 2 (1 pt border on each side)
width = 18 width = 18
cardIconHeight = y + offset cardIconHeight = y + offset
countHeight = cardIconHeight - 4 countHeight = cardIconHeight - 4
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', 'card.png'), self.canvas.drawImage(
x, countHeight, 16, 16, preserveAspectRatio=True, mask='auto') os.path.join(self.options.data_path, 'images', 'card.png'),
x,
countHeight,
16,
16,
preserveAspectRatio=True,
mask='auto')
self.canvas.setFont(self.fontNameBold, 10) self.canvas.setFont(self.fontNameBold, 10)
count = str(card.count) count = str(card.count)
@ -312,27 +336,51 @@ class DividerDrawer(object):
potSize = 11 potSize = 11
if card.debtcost: if card.debtcost:
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', 'debt.png'), self.canvas.drawImage(
x, coinHeight, 16, 16, preserveAspectRatio=True, os.path.join(self.options.data_path, 'images', 'debt.png'),
mask=[255, 255, 255, 255, 255, 255]) x,
coinHeight,
16,
16,
preserveAspectRatio=True,
mask=[255, 255, 255, 255, 255, 255])
cost = str(card.debtcost) cost = str(card.debtcost)
if card.cost != "" and int(card.cost) > 0: if card.cost != "" and int(card.cost) > 0:
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', 'coin_small.png'), x + 17, self.canvas.drawImage(
coinHeight, 16, 16, preserveAspectRatio=True, os.path.join(self.options.data_path, 'images',
mask=[255, 255, 255, 255, 255, 255]) 'coin_small.png'),
x + 17,
coinHeight,
16,
16,
preserveAspectRatio=True,
mask=[255, 255, 255, 255, 255, 255])
self.canvas.setFont(self.fontNameBold, 12) self.canvas.setFont(self.fontNameBold, 12)
self.canvas.drawCentredString(x + 8 + 17, costHeight, str(card.cost)) self.canvas.drawCentredString(x + 8 + 17, costHeight,
str(card.cost))
self.canvas.setFillColorRGB(0, 0, 0) self.canvas.setFillColorRGB(0, 0, 0)
width += 16 width += 16
self.canvas.setFillColorRGB(1, 1, 1) self.canvas.setFillColorRGB(1, 1, 1)
else: else:
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', 'coin_small.png'), self.canvas.drawImage(
x, coinHeight, 16, 16, preserveAspectRatio=True, mask='auto') os.path.join(self.options.data_path, 'images',
'coin_small.png'),
x,
coinHeight,
16,
16,
preserveAspectRatio=True,
mask='auto')
cost = str(card.cost) cost = str(card.cost)
if card.potcost: if card.potcost:
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', 'potion.png'), x + 17, self.canvas.drawImage(
potHeight, potSize, potSize, preserveAspectRatio=True, os.path.join(self.options.data_path, 'images', 'potion.png'),
mask=[255, 255, 255, 255, 255, 255]) x + 17,
potHeight,
potSize,
potSize,
preserveAspectRatio=True,
mask=[255, 255, 255, 255, 255, 255])
width += potSize width += potSize
self.canvas.setFont(self.fontNameBold, 12) self.canvas.setFont(self.fontNameBold, 12)
@ -343,17 +391,24 @@ class DividerDrawer(object):
def drawSetIcon(self, setImage, x, y): def drawSetIcon(self, setImage, x, y):
# set image # set image
self.canvas.drawImage( self.canvas.drawImage(
os.path.join(self.options.data_path, 'images', setImage), x, y, 14, 12, mask='auto') os.path.join(self.options.data_path, 'images', setImage),
x,
y,
14,
12,
mask='auto')
def nameWidth(self, name, fontSize): def nameWidth(self, name, fontSize):
w = 0 w = 0
name_parts = name.split() name_parts = name.split()
for i, part in enumerate(name_parts): for i, part in enumerate(name_parts):
if i != 0: if i != 0:
w += pdfmetrics.stringWidth(' ', self.fontNameRegular, fontSize) w += pdfmetrics.stringWidth(' ', self.fontNameRegular,
w += pdfmetrics.stringWidth(part[0], self.fontNameRegular, fontSize) fontSize)
w += pdfmetrics.stringWidth(part[1:], w += pdfmetrics.stringWidth(part[0], self.fontNameRegular,
self.fontNameRegular, fontSize - 2) fontSize)
w += pdfmetrics.stringWidth(part[1:], self.fontNameRegular,
fontSize - 2)
return w return w
def drawTab(self, card, rightSide, wrapper="no"): def drawTab(self, card, rightSide, wrapper="no"):
@ -363,23 +418,24 @@ class DividerDrawer(object):
translate_x = self.options.dividerWidth / 2 - self.options.labelWidth / 2 translate_x = self.options.dividerWidth / 2 - self.options.labelWidth / 2
translate_y = self.options.dividerHeight - self.options.labelHeight translate_y = self.options.dividerHeight - self.options.labelHeight
elif not rightSide: elif not rightSide:
translate_x = self.options.dividerWidth - self.options.labelWidth translate_x = self.options.dividerWidth - self.options.labelWidth
translate_y = self.options.dividerHeight - self.options.labelHeight translate_y = self.options.dividerHeight - self.options.labelHeight
else: else:
translate_x = 0 translate_x = 0
translate_y = self.options.dividerHeight - self.options.labelHeight translate_y = self.options.dividerHeight - self.options.labelHeight
if wrapper == "back": if wrapper == "back":
translate_y = self.options.labelHeight translate_y = self.options.labelHeight
if card.isExpansion() and self.options.centre_expansion_dividers: if card.isExpansion() and self.options.centre_expansion_dividers:
translate_x = self.options.dividerWidth / 2 + self.options.labelWidth / 2 translate_x = self.options.dividerWidth / 2 + self.options.labelWidth / 2
elif not rightSide: elif not rightSide:
translate_x = self.options.dividerWidth translate_x = self.options.dividerWidth
else: else:
translate_x = self.options.labelWidth translate_x = self.options.labelWidth
if wrapper == "front": if wrapper == "front":
translate_y = translate_y + self.options.dividerHeight + 2.0 * card.getStackHeight(self.options.thickness) translate_y = translate_y + self.options.dividerHeight + 2.0 * card.getStackHeight(
self.options.thickness)
self.canvas.translate(translate_x, translate_y) self.canvas.translate(translate_x, translate_y)
@ -397,17 +453,24 @@ class DividerDrawer(object):
# draw banner # draw banner
img = card.getType().getNoCoinTabImageFile() img = card.getType().getNoCoinTabImageFile()
if not self.options.no_tab_artwork and img: if not self.options.no_tab_artwork and img:
self.canvas.drawImage(os.path.join(self.options.data_path, 'images', img), 1, 0, self.canvas.drawImage(
self.options.labelWidth - os.path.join(self.options.data_path, 'images', img),
2, self.options.labelHeight - 1, 1,
preserveAspectRatio=False, anchor='n', mask='auto') 0,
self.options.labelWidth - 2,
self.options.labelHeight - 1,
preserveAspectRatio=False,
anchor='n',
mask='auto')
# draw cost # draw cost
if not card.isExpansion() and not card.isBlank() and not card.isLandmark() and not card.isType('Trash'): if not card.isExpansion() and not card.isBlank(
) and not card.isLandmark() and not card.isType('Trash'):
if 'tab' in self.options.cost: if 'tab' in self.options.cost:
textInset = 4 textInset = 4
textInset += self.drawCost(card, textInset, textHeight, textInset += self.drawCost(
card.getType().getTabCostHeightOffset()) card, textInset, textHeight,
card.getType().getTabCostHeightOffset())
else: else:
textInset = 6 textInset = 6
else: else:
@ -424,7 +487,8 @@ class DividerDrawer(object):
if setText is None: if setText is None:
setText = "" setText = ""
self.canvas.drawCentredString(self.options.labelWidth - 10, textHeight + 2, setText) self.canvas.drawCentredString(self.options.labelWidth - 10,
textHeight + 2, setText)
textInsetRight = 15 textInsetRight = 15
else: else:
setImage = card.setImage() setImage = card.setImage()
@ -469,13 +533,16 @@ class DividerDrawer(object):
h -= h / 2 h -= h / 2
words = line.split() words = line.split()
NotRightEdge = ( not self.options.tab_name_align == "right" NotRightEdge = (
and (self.options.tab_name_align == "centre" or rightSide or not self.options.tab_name_align == "edge")) not self.options.tab_name_align == "right" and
(self.options.tab_name_align == "centre" or rightSide or
not self.options.tab_name_align == "edge"))
if wrapper == "back" and not self.options.tab_name_align == "centre": if wrapper == "back" and not self.options.tab_name_align == "centre":
NotRightEdge = not NotRightEdge NotRightEdge = not NotRightEdge
if NotRightEdge: if NotRightEdge:
if self.options.tab_name_align == "centre": if self.options.tab_name_align == "centre":
w = self.options.labelWidth / 2 - self.nameWidth(line, fontSize) / 2 w = self.options.labelWidth / 2 - self.nameWidth(
line, fontSize) / 2
else: else:
w = textInset w = textInset
@ -483,7 +550,9 @@ class DividerDrawer(object):
self.canvas.setFont(self.fontNameRegular, fontSize) self.canvas.setFont(self.fontNameRegular, fontSize)
if text != ' ': if text != ' ':
self.canvas.drawString(w, h, text) self.canvas.drawString(w, h, text)
return pdfmetrics.stringWidth(text, self.fontNameRegular, fontSize) return pdfmetrics.stringWidth(text, self.fontNameRegular,
fontSize)
for i, word in enumerate(words): for i, word in enumerate(words):
if i != 0: if i != 0:
w += drawWordPiece(' ', fontSize) w += drawWordPiece(' ', fontSize)
@ -501,7 +570,9 @@ class DividerDrawer(object):
self.canvas.setFont(self.fontNameRegular, fontSize) self.canvas.setFont(self.fontNameRegular, fontSize)
if text != ' ': if text != ' ':
self.canvas.drawRightString(w, h, text) self.canvas.drawRightString(w, h, text)
return -pdfmetrics.stringWidth(text, self.fontNameRegular, fontSize) return -pdfmetrics.stringWidth(text, self.fontNameRegular,
fontSize)
for i, word in enumerate(words): for i, word in enumerate(words):
w += drawWordPiece(word[1:], fontSize - 2) w += drawWordPiece(word[1:], fontSize - 2)
w += drawWordPiece(word[0], fontSize) w += drawWordPiece(word[0], fontSize)
@ -510,20 +581,26 @@ class DividerDrawer(object):
if wrapper == "front" and card.getCardCount() >= 5: if wrapper == "front" and card.getCardCount() >= 5:
# Print smaller version of name on the top wrapper edge # Print smaller version of name on the top wrapper edge
self.canvas.translate(0 , -card.getStackHeight(self.options.thickness)) # move into area used by the wrapper self.canvas.translate(0, -card.getStackHeight(
fontSize = 8 # use the smallest font self.options.thickness)) # move into area used by the wrapper
fontSize = 8 # use the smallest font
self.canvas.setFont(self.fontNameRegular, fontSize) self.canvas.setFont(self.fontNameRegular, fontSize)
textHeight = fontSize - 2 textHeight = fontSize - 2
textHeight = card.getStackHeight(self.options.thickness) / 2 - textHeight / 2 textHeight = card.getStackHeight(
self.options.thickness) / 2 - textHeight / 2
h = textHeight h = textHeight
words = name.split() words = name.split()
w = self.options.labelWidth / 2 - self.nameWidth(name, fontSize) / 2 w = self.options.labelWidth / 2 - self.nameWidth(name,
fontSize) / 2
def drawWordPiece(text, fontSize): def drawWordPiece(text, fontSize):
self.canvas.setFont(self.fontNameRegular, fontSize) self.canvas.setFont(self.fontNameRegular, fontSize)
if text != ' ': if text != ' ':
self.canvas.drawString(w, h, text) self.canvas.drawString(w, h, text)
return pdfmetrics.stringWidth(text, self.fontNameRegular, fontSize) return pdfmetrics.stringWidth(text, self.fontNameRegular,
fontSize)
for i, word in enumerate(words): for i, word in enumerate(words):
if i != 0: if i != 0:
w += drawWordPiece(' ', fontSize) w += drawWordPiece(' ', fontSize)
@ -540,11 +617,13 @@ class DividerDrawer(object):
# Figure out if any translation needs to be done # Figure out if any translation needs to be done
if wrapper == "back": if wrapper == "back":
self.canvas.translate(self.options.dividerWidth, self.options.dividerHeight) self.canvas.translate(self.options.dividerWidth,
self.options.dividerHeight)
self.canvas.rotate(180) self.canvas.rotate(180)
if wrapper == "front": if wrapper == "front":
self.canvas.translate( 0 , self.options.dividerHeight + card.getStackHeight(self.options.thickness)) self.canvas.translate(0, self.options.dividerHeight +
card.getStackHeight(self.options.thickness))
if wrapper == "front" or wrapper == "back": if wrapper == "front" or wrapper == "back":
if self.options.notch_width1 > 0: if self.options.notch_width1 > 0:
@ -565,7 +644,8 @@ class DividerDrawer(object):
drewTopIcon = True drewTopIcon = True
if self.options.count: if self.options.count:
self.drawCardCount(card, Image_x, totalHeight - usedHeight - 0.5 * cm) self.drawCardCount(card, Image_x,
totalHeight - usedHeight - 0.5 * cm)
drewTopIcon = True drewTopIcon = True
if drewTopIcon: if drewTopIcon:
@ -578,7 +658,7 @@ class DividerDrawer(object):
elif divider_text == "rules": elif divider_text == "rules":
# Add the extra rules text to the divider # Add the extra rules text to the divider
if card.extra: if card.extra:
descriptions = (card.extra,) descriptions = (card.extra, )
else: else:
# Asked for rules and they don't exist, so don't print anything # Asked for rules and they don't exist, so don't print anything
return return
@ -625,7 +705,13 @@ class DividerDrawer(object):
self.canvas.restoreState() self.canvas.restoreState()
def drawDivider(self, card, x, y, isBack=False, divider_text="card", divider_text2="rules"): def drawDivider(self,
card,
x,
y,
isBack=False,
divider_text="card",
divider_text2="rules"):
# figure out whether the tab should go on the right side or not # figure out whether the tab should go on the right side or not
if self.options.tab_side == "right": if self.options.tab_side == "right":
rightSide = isBack rightSide = isBack
@ -640,15 +726,18 @@ class DividerDrawer(object):
# apply the transforms to get us to the corner of the current card # apply the transforms to get us to the corner of the current card
self.canvas.resetTransforms() self.canvas.resetTransforms()
self.canvas.translate(self.options.horizontalMargin, self.options.verticalMargin) self.canvas.translate(self.options.horizontalMargin,
self.options.verticalMargin)
if isBack: if isBack:
self.canvas.translate(self.options.back_offset, self.options.back_offset_height) self.canvas.translate(self.options.back_offset,
self.options.back_offset_height)
self.canvas.translate(x * self.options.dividerWidthReserved, self.canvas.translate(x * self.options.dividerWidthReserved,
y * self.options.dividerHeightReserved) y * self.options.dividerHeightReserved)
# actual drawing # actual drawing
if not self.options.tabs_only: if not self.options.tabs_only:
self.drawOutline(card, x, y, rightSide, isBack, card.getType().getTypeNames() == ('Expansion',)) self.drawOutline(card, x, y, rightSide, isBack,
card.getType().getTypeNames() == ('Expansion', ))
if self.options.wrapper: if self.options.wrapper:
wrap = "front" wrap = "front"
@ -671,7 +760,8 @@ class DividerDrawer(object):
minFontsize = 6 minFontsize = 6
fontname = self.fontNameRegular fontname = self.fontNameRegular
font = pdfmetrics.getFont(fontname) font = pdfmetrics.getFont(fontname)
fontHeightRelative = (font.face.ascent + abs(font.face.descent)) / 1000.0 fontHeightRelative = (
font.face.ascent + abs(font.face.descent)) / 1000.0
canFit = False canFit = False
@ -685,8 +775,8 @@ class DividerDrawer(object):
'width': self.options.paperheight}] 'width': self.options.paperheight}]
for layout in layouts: for layout in layouts:
availableMargin = layout[ availableMargin = layout['totalMarginHeight'] - layout[
'totalMarginHeight'] - layout['minMarginHeight'] 'minMarginHeight']
fontsize = availableMargin / fontHeightRelative fontsize = availableMargin / fontHeightRelative
fontsize = min(maxFontsize, fontsize) fontsize = min(maxFontsize, fontsize)
if fontsize >= minFontsize: if fontsize >= minFontsize:
@ -725,7 +815,8 @@ class DividerDrawer(object):
def drawDividers(self, cards): def drawDividers(self, cards):
# split into pages # split into pages
cards = split(cards, self.options.numDividersVertical * self.options.numDividersHorizontal) cards = split(cards, self.options.numDividersVertical *
self.options.numDividersHorizontal)
# Starting with tabs on the left or the right? # Starting with tabs on the left or the right?
if self.options.tab_side in ["right-alternate", "right"]: if self.options.tab_side in ["right-alternate", "right"]:
@ -738,14 +829,21 @@ class DividerDrawer(object):
# remember whether we start with odd or even divider for tab # remember whether we start with odd or even divider for tab
# location # location
pageStartOdd = self.odd pageStartOdd = self.odd
if not self.options.no_page_footer and (not self.options.tabs_only and self.options.order != "global"): if not self.options.no_page_footer and (
not self.options.tabs_only and
self.options.order != "global"):
self.drawSetNames(pageCards) self.drawSetNames(pageCards)
for i, card in enumerate(pageCards): for i, card in enumerate(pageCards):
# print card # print card
x = i % self.options.numDividersHorizontal x = i % self.options.numDividersHorizontal
y = i / self.options.numDividersHorizontal y = i / self.options.numDividersHorizontal
self.canvas.saveState() self.canvas.saveState()
self.drawDivider(card, x, self.options.numDividersVertical - 1 - y, isBack=False, divider_text=self.options.text_front, divider_text2=self.options.text_back) self.drawDivider(card,
x,
self.options.numDividersVertical - 1 - y,
isBack=False,
divider_text=self.options.text_front,
divider_text2=self.options.text_back)
self.canvas.restoreState() self.canvas.restoreState()
self.odd = not self.odd self.odd = not self.odd
self.canvas.showPage() self.canvas.showPage()
@ -760,10 +858,15 @@ class DividerDrawer(object):
self.odd = pageStartOdd self.odd = pageStartOdd
for i, card in enumerate(pageCards): for i, card in enumerate(pageCards):
# print card # print card
x = (self.options.numDividersHorizontal - 1 - i) % self.options.numDividersHorizontal x = (self.options.numDividersHorizontal - 1 - i
) % self.options.numDividersHorizontal
y = i / self.options.numDividersHorizontal y = i / self.options.numDividersHorizontal
self.canvas.saveState() self.canvas.saveState()
self.drawDivider(card, x, self.options.numDividersVertical - 1 - y, isBack=True, divider_text=self.options.text_back) self.drawDivider(card,
x,
self.options.numDividersVertical - 1 - y,
isBack=True,
divider_text=self.options.text_back)
self.canvas.restoreState() self.canvas.restoreState()
self.odd = not self.odd self.odd = not self.odd
self.canvas.showPage() self.canvas.showPage()

View File

@ -1,391 +0,0 @@
#!/usr/bin/env python
"""
Setuptools bootstrapping installer.
Run this script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import tempfile
import zipfile
import optparse
import subprocess
import platform
import textwrap
import contextlib
import warnings
from distutils import log
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "18.5"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
DEFAULT_SAVE_DIR = os.curdir
def _python_cmd(*args):
"""
Execute a command.
Return True if the command succeeded.
"""
args = (sys.executable,) + args
return subprocess.call(args) == 0
def _install(archive_filename, install_args=()):
"""Install Setuptools."""
with archive_context(archive_filename):
# installing
log.warn('Installing Setuptools')
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
def _build_egg(egg, archive_filename, to_dir):
"""Build Setuptools egg."""
with archive_context(archive_filename):
# building an egg
log.warn('Building a Setuptools egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
class ContextualZipFile(zipfile.ZipFile):
"""Supplement ZipFile class to support context manager for Python 2.6."""
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def __new__(cls, *args, **kwargs):
"""Construct a ZipFile or ContextualZipFile as appropriate."""
if hasattr(zipfile.ZipFile, '__exit__'):
return zipfile.ZipFile(*args, **kwargs)
return super(ContextualZipFile, cls).__new__(cls)
@contextlib.contextmanager
def archive_context(filename):
"""
Unzip filename to a temporary directory, set to the cwd.
The unzipped target is cleaned up after.
"""
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
with ContextualZipFile(filename) as archive:
archive.extractall()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
yield
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _do_download(version, download_base, to_dir, download_delay):
"""Download Setuptools."""
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
archive = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, archive, to_dir)
sys.path.insert(0, egg)
# Remove previously-imported pkg_resources if present (see
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
if 'pkg_resources' in sys.modules:
del sys.modules['pkg_resources']
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=DEFAULT_SAVE_DIR, download_delay=15):
"""
Ensure that a setuptools version is installed.
Return None. Raise SystemExit if the requested version
or later cannot be installed.
"""
to_dir = os.path.abspath(to_dir)
# prior to importing, capture the module state for
# representative modules.
rep_modules = 'pkg_resources', 'setuptools'
imported = set(sys.modules).intersection(rep_modules)
try:
import pkg_resources
pkg_resources.require("setuptools>=" + version)
# a suitable version is already installed
return
except ImportError:
# pkg_resources not available; setuptools is not installed; download
pass
except pkg_resources.DistributionNotFound:
# no version of setuptools was found; allow download
pass
except pkg_resources.VersionConflict as VC_err:
if imported:
_conflict_bail(VC_err, version)
# otherwise, unload pkg_resources to allow the downloaded version to
# take precedence.
del pkg_resources
_unload_pkg_resources()
return _do_download(version, download_base, to_dir, download_delay)
def _conflict_bail(VC_err, version):
"""
Setuptools was imported prior to invocation, so it is
unsafe to unload it. Bail out.
"""
conflict_tmpl = textwrap.dedent("""
The required version of setuptools (>={version}) is not available,
and can't be installed while this script is running. Please
install a more recent version first, using
'easy_install -U setuptools'.
(Currently using {VC_err.args[0]!r})
""")
msg = conflict_tmpl.format(**locals())
sys.stderr.write(msg)
sys.exit(2)
def _unload_pkg_resources():
del_modules = [
name for name in sys.modules
if name.startswith('pkg_resources')
]
for mod_name in del_modules:
del sys.modules[mod_name]
def _clean_check(cmd, target):
"""
Run the command to download target.
If the command fails, clean up before re-raising the error.
"""
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
if os.access(target, os.F_OK):
os.unlink(target)
raise
def download_file_powershell(url, target):
"""
Download the file at url to target using Powershell.
Powershell will validate trust.
Raise an exception if the command cannot complete.
"""
target = os.path.abspath(target)
ps_cmd = (
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
"[System.Net.CredentialCache]::DefaultCredentials; "
"(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
% vars()
)
cmd = [
'powershell',
'-Command',
ps_cmd,
]
_clean_check(cmd, target)
def has_powershell():
"""Determine if Powershell is available."""
if platform.system() != 'Windows':
return False
cmd = ['powershell', '-Command', 'echo test']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_powershell.viable = has_powershell
def download_file_curl(url, target):
cmd = ['curl', url, '--silent', '--output', target]
_clean_check(cmd, target)
def has_curl():
cmd = ['curl', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_curl.viable = has_curl
def download_file_wget(url, target):
cmd = ['wget', url, '--quiet', '--output-document', target]
_clean_check(cmd, target)
def has_wget():
cmd = ['wget', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_wget.viable = has_wget
def download_file_insecure(url, target):
"""Use Python to download the file, without connection authentication."""
src = urlopen(url)
try:
# Read all the data in one block.
data = src.read()
finally:
src.close()
# Write all the data in one block to avoid creating a partial file.
with open(target, "wb") as dst:
dst.write(data)
download_file_insecure.viable = lambda: True
def get_best_downloader():
downloaders = (
download_file_powershell,
download_file_curl,
download_file_wget,
download_file_insecure,
)
viable_downloaders = (dl for dl in downloaders if dl.viable())
return next(viable_downloaders, None)
def download_setuptools(
version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=DEFAULT_SAVE_DIR, delay=15,
downloader_factory=get_best_downloader):
"""
Download setuptools from a specified location and return its filename.
`version` should be a valid setuptools version number that is available
as an sdist for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
``downloader_factory`` should be a function taking no arguments and
returning a function for downloading a URL to a target.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
zip_name = "setuptools-%s.zip" % version
url = download_base + zip_name
saveto = os.path.join(to_dir, zip_name)
if not os.path.exists(saveto): # Avoid repeated downloads
log.warn("Downloading %s", url)
downloader = downloader_factory()
downloader(url, saveto)
return os.path.realpath(saveto)
def _build_install_args(options):
"""
Build the arguments to 'python setup.py install' on the setuptools package.
Returns list of command line arguments.
"""
return ['--user'] if options.user_install else []
def _parse_args():
"""Parse the command line for options."""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the setuptools package')
parser.add_option(
'--insecure', dest='downloader_factory', action='store_const',
const=lambda: download_file_insecure, default=get_best_downloader,
help='Use internal, non-validating downloader'
)
parser.add_option(
'--version', help="Specify which version to download",
default=DEFAULT_VERSION,
)
parser.add_option(
'--to-dir',
help="Directory to save (and re-use) package",
default=DEFAULT_SAVE_DIR,
)
options, args = parser.parse_args()
# positional arguments are ignored
return options
def _download_args(options):
"""Return args for download_setuptools function from cmdline args."""
return dict(
version=options.version,
download_base=options.download_base,
downloader_factory=options.downloader_factory,
to_dir=options.to_dir,
)
def main():
"""Install or upgrade setuptools and EasyInstall."""
options = _parse_args()
archive = download_setuptools(**_download_args(options))
return _install(archive, _build_install_args(options))
if __name__ == '__main__':
sys.exit(main())

View File

@ -23,4 +23,3 @@ setup(
author_email="sumpfork@mailmight.net", author_email="sumpfork@mailmight.net",
description="Divider Generation for the Dominion Card Game" description="Divider Generation for the Dominion Card Game"
) )

View File

@ -6,7 +6,7 @@ from ..domdiv import cards as domdiv_cards
class TestCardDB(unittest.TestCase): class TestCardDB(unittest.TestCase):
def test_cardread(self): def test_cardread(self):
options, args = domdiv.parse_opts(['commandname']) options = domdiv.parse_opts([])
options.data_path = '.' options.data_path = '.'
cards = domdiv.read_write_card_data(options) cards = domdiv.read_write_card_data(options)
self.assertEquals(len(cards), 383) self.assertEquals(len(cards), 383)
@ -36,13 +36,13 @@ class TestCardDB(unittest.TestCase):
def test_languages(self): def test_languages(self):
# for now, just test that they load # for now, just test that they load
options, args = domdiv.parse_opts(['commandname', '--language', 'it']) options = domdiv.parse_opts(['--language', 'it'])
options.data_path = '.' options.data_path = '.'
cards = domdiv.read_write_card_data(options) cards = domdiv.read_write_card_data(options)
self.assertTrue(cards, 'Italians cards did not read properly') self.assertTrue(cards, 'Italians cards did not read properly')
self.assertIn("Maledizione", [card.name for card in cards]) self.assertIn("Maledizione", [card.name for card in cards])
options, args = domdiv.parse_opts(['commandname', '--language', 'de']) options = domdiv.parse_opts(['--language', 'de'])
options.data_path = '.' options.data_path = '.'
cards = domdiv.read_write_card_data(options) cards = domdiv.read_write_card_data(options)
self.assertTrue(cards, 'German cards did not read properly') self.assertTrue(cards, 'German cards did not read properly')

13
tests/codestyle_tests.py Normal file
View File

@ -0,0 +1,13 @@
import unittest
import pycodestyle
import glob
class TestCodeFormat(unittest.TestCase):
def test_conformance(self):
"""Test that we conform to PEP-8."""
style = pycodestyle.StyleGuide(max_line_length=120)
result = style.check_files(glob.glob('*.py') + glob.glob('domdiv/*.py') + glob.glob('tests/*.py'))
self.assertEqual(result.total_errors, 0,
"Found code style errors (and warnings).")

View File

@ -7,7 +7,7 @@ class TestLayout(unittest.TestCase):
def test_horizontal(self): def test_horizontal(self):
# should be the default # should be the default
options, args = domdiv.parse_opts(['commandname']) options = domdiv.parse_opts([])
self.assertEquals(options.orientation, 'horizontal') self.assertEquals(options.orientation, 'horizontal')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.numDividersHorizontal, 2) self.assertEquals(options.numDividersHorizontal, 2)
@ -17,7 +17,7 @@ class TestLayout(unittest.TestCase):
self.assertEquals(options.dividerHeight, 5.9 * cm + options.labelHeight) self.assertEquals(options.dividerHeight, 5.9 * cm + options.labelHeight)
def test_vertical(self): def test_vertical(self):
options, args = domdiv.parse_opts(['commandname', '--orientation', 'vertical']) options = domdiv.parse_opts(['--orientation', 'vertical'])
self.assertEquals(options.orientation, 'vertical') self.assertEquals(options.orientation, 'vertical')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.numDividersHorizontal, 3) self.assertEquals(options.numDividersHorizontal, 3)
@ -27,9 +27,8 @@ class TestLayout(unittest.TestCase):
self.assertEquals(options.dividerHeight, 9.1 * cm + options.labelHeight) self.assertEquals(options.dividerHeight, 9.1 * cm + options.labelHeight)
def test_sleeved(self): def test_sleeved(self):
options, args = domdiv.parse_opts(['commandname', '--size', 'sleeved']) options = domdiv.parse_opts(['--size', 'sleeved'])
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.dividerWidth, 9.4 * cm) self.assertEquals(options.dividerWidth, 9.4 * cm)
self.assertEquals(options.labelHeight, 0.9 * cm) self.assertEquals(options.labelHeight, 0.9 * cm)
self.assertEquals(options.dividerHeight, 6.15 * cm + options.labelHeight) self.assertEquals(options.dividerHeight, 6.15 * cm + options.labelHeight)

View File

@ -1,6 +1,5 @@
import unittest import unittest
from .. import domdiv from .. import domdiv
from reportlab.lib.units import cm
class TestTextTabs(unittest.TestCase): class TestTextTabs(unittest.TestCase):
@ -10,11 +9,11 @@ class TestTextTabs(unittest.TestCase):
#################### ####################
def test_text_tabs_default(self): def test_text_tabs_default(self):
# should be the default # should be the default
options, args = domdiv.parse_opts(['commandname']) options = domdiv.parse_opts([])
self.assertEquals(options.text_front, 'card') self.assertEquals(options.text_front, 'card')
self.assertEquals(options.text_back, 'rules') self.assertEquals(options.text_back, 'rules')
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
@ -22,239 +21,280 @@ class TestTextTabs(unittest.TestCase):
# Card Text Tests # Card Text Tests
#################### ####################
def test_text_card_rules(self): def test_text_card_rules(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'card', '--back', 'rules']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'card') ['--front', 'card', '--back', 'rules'])
self.assertEquals(options.text_back, 'rules') self.assertEquals(options.text_front, 'card')
self.assertEquals(options.text_back, 'rules')
def test_text_card_blank(self): def test_text_card_blank(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'card', '--back', 'blank']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'card') ['--front', 'card', '--back', 'blank'])
self.assertEquals(options.text_back, 'blank') self.assertEquals(options.text_front, 'card')
self.assertEquals(options.text_back, 'blank')
def test_text_card_card(self): def test_text_card_card(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'card', '--back', 'card']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'card') ['--front', 'card', '--back', 'card'])
self.assertEquals(options.text_back, 'card') self.assertEquals(options.text_front, 'card')
self.assertEquals(options.text_back, 'card')
def test_text_card_none(self): def test_text_card_none(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'card', '--back', 'none']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'card') ['--front', 'card', '--back', 'none'])
self.assertEquals(options.text_back, 'none') self.assertEquals(options.text_front, 'card')
self.assertEquals(options.text_back, 'none')
def test_text_rules_rules(self): def test_text_rules_rules(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'rules', '--back', 'rules']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'rules') ['--front', 'rules', '--back', 'rules'])
self.assertEquals(options.text_back, 'rules') self.assertEquals(options.text_front, 'rules')
self.assertEquals(options.text_back, 'rules')
def test_text_rules_blank(self): def test_text_rules_blank(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'rules', '--back', 'blank']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'rules') ['--front', 'rules', '--back', 'blank'])
self.assertEquals(options.text_back, 'blank') self.assertEquals(options.text_front, 'rules')
self.assertEquals(options.text_back, 'blank')
def test_text_rules_card(self): def test_text_rules_card(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'rules', '--back', 'card']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'rules') ['--front', 'rules', '--back', 'card'])
self.assertEquals(options.text_back, 'card') self.assertEquals(options.text_front, 'rules')
self.assertEquals(options.text_back, 'card')
def test_text_rules_none(self): def test_text_rules_none(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'rules', '--back', 'none']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'rules') ['--front', 'rules', '--back', 'none'])
self.assertEquals(options.text_back, 'none') self.assertEquals(options.text_front, 'rules')
self.assertEquals(options.text_back, 'none')
def test_text_blank_rules(self): def test_text_blank_rules(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'blank', '--back', 'rules']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'blank') ['--front', 'blank', '--back', 'rules'])
self.assertEquals(options.text_back, 'rules') self.assertEquals(options.text_front, 'blank')
self.assertEquals(options.text_back, 'rules')
def test_text_blank_blank(self): def test_text_blank_blank(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'blank', '--back', 'blank']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'blank') ['--front', 'blank', '--back', 'blank'])
self.assertEquals(options.text_back, 'blank') self.assertEquals(options.text_front, 'blank')
self.assertEquals(options.text_back, 'blank')
def test_text_blank_card(self): def test_text_blank_card(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'blank', '--back', 'card']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'blank') ['--front', 'blank', '--back', 'card'])
self.assertEquals(options.text_back, 'card') self.assertEquals(options.text_front, 'blank')
self.assertEquals(options.text_back, 'card')
def test_text_blank_none(self): def test_text_blank_none(self):
options, args = domdiv.parse_opts(['commandname', '--front', 'blank', '--back', 'none']) options = domdiv.parse_opts(
self.assertEquals(options.text_front, 'blank') ['--front', 'blank', '--back', 'none'])
self.assertEquals(options.text_back, 'none') self.assertEquals(options.text_front, 'blank')
self.assertEquals(options.text_back, 'none')
#################### ####################
# Card Tab Tests # Card Tab Tests
#################### ####################
# --tab_name_align left # --tab_name_align left
def test_tab_left_left(self): def test_tab_left_left(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'left', '--tab_side', 'left']) options = domdiv.parse_opts(
['--tab_name_align', 'left', '--tab_side', 'left'])
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
def test_tab_left_right(self): def test_tab_left_right(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'left', '--tab_side', 'right']) options = domdiv.parse_opts(
['--tab_name_align', 'left', '--tab_side', 'right'])
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
def test_tab_left_leftalt(self): def test_tab_left_leftalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'left', '--tab_side', 'left-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'left', '--tab_side',
'left-alternate'])
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
def test_tab_left_rightalt(self): def test_tab_left_rightalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'left', '--tab_side', 'right-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'left', '--tab_side',
'right-alternate'])
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
def test_tab_left_full(self): def test_tab_left_full(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'left', '--tab_side', 'full']) options = domdiv.parse_opts(
['--tab_name_align', 'left', '--tab_side', 'full'])
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') self.assertEquals(options.tab_name_align, 'left')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
# --tab_name_align right # --tab_name_align right
def test_tab_right_left(self): def test_tab_right_left(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'right', '--tab_side', 'left']) options = domdiv.parse_opts(
['--tab_name_align', 'right', '--tab_side', 'left'])
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
def test_tab_right_right(self): def test_tab_right_right(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'right', '--tab_side', 'right']) options = domdiv.parse_opts(['--tab_name_align',
'right', '--tab_side', 'right'])
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
def test_tab_right_leftalt(self): def test_tab_right_leftalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'right', '--tab_side', 'left-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'right', '--tab_side',
'left-alternate'])
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
def test_tab_right_rightalt(self): def test_tab_right_rightalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'right', '--tab_side', 'right-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'right', '--tab_side',
'right-alternate'])
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
def test_tab_right_full(self): def test_tab_right_full(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'right', '--tab_side', 'full']) options = domdiv.parse_opts(
['--tab_name_align', 'right', '--tab_side', 'full'])
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'right') self.assertEquals(options.tab_name_align, 'right')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
# --tab_name_align edge # --tab_name_align edge
def test_tab_edge_left(self): def test_tab_edge_left(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'edge', '--tab_side', 'left']) options = domdiv.parse_opts(
['--tab_name_align', 'edge', '--tab_side', 'left'])
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
def test_tab_edge_right(self): def test_tab_edge_right(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'edge', '--tab_side', 'right']) options = domdiv.parse_opts(
['--tab_name_align', 'edge', '--tab_side', 'right'])
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
def test_tab_edge_leftalt(self): def test_tab_edge_leftalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'edge', '--tab_side', 'left-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'edge', '--tab_side',
'left-alternate'])
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
def test_tab_edge_rightalt(self): def test_tab_edge_rightalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'edge', '--tab_side', 'right-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'edge', '--tab_side',
'right-alternate'])
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
def test_tab_edge_full(self): def test_tab_edge_full(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'edge', '--tab_side', 'full']) options = domdiv.parse_opts(
['--tab_name_align', 'edge', '--tab_side', 'full'])
self.assertEquals(options.tab_name_align, 'edge') self.assertEquals(options.tab_name_align, 'edge')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'left') # special check for odd condition self.assertEquals(options.tab_name_align,
self.assertEquals(options.tab_side, 'full') 'left') # special check for odd condition
self.assertEquals(options.tab_side, 'full')
# --tab_name_align centre # --tab_name_align centre
def test_tab_centre_left(self): def test_tab_centre_left(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'centre', '--tab_side', 'left']) options = domdiv.parse_opts(['--tab_name_align',
'centre', '--tab_side', 'left'])
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
def test_tab_centre_right(self): def test_tab_centre_right(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'centre', '--tab_side', 'right']) options = domdiv.parse_opts(['--tab_name_align',
'centre', '--tab_side', 'right'])
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'right') self.assertEquals(options.tab_side, 'right')
def test_tab_centre_leftalt(self): def test_tab_centre_leftalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'centre', '--tab_side', 'left-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'centre', '--tab_side',
'left-alternate'])
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'left-alternate') self.assertEquals(options.tab_side, 'left-alternate')
def test_tab_centre_rightalt(self): def test_tab_centre_rightalt(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'centre', '--tab_side', 'right-alternate']) options = domdiv.parse_opts(
['--tab_name_align', 'centre', '--tab_side',
'right-alternate'])
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'right-alternate') self.assertEquals(options.tab_side, 'right-alternate')
def test_tab_centre_full(self): def test_tab_centre_full(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'centre', '--tab_side', 'full']) options = domdiv.parse_opts(['--tab_name_align',
'centre', '--tab_side', 'full'])
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') self.assertEquals(options.tab_name_align, 'centre')
self.assertEquals(options.tab_side, 'full') self.assertEquals(options.tab_side, 'full')
# --tab_name_align center. Just do one since this is an alias to centre # --tab_name_align center. Just do one since this is an alias to centre
def test_tab_center_left(self): def test_tab_center_left(self):
options, args = domdiv.parse_opts(['commandname', '--tab_name_align', 'center', '--tab_side', 'left']) options = domdiv.parse_opts(['--tab_name_align',
'center', '--tab_side', 'left'])
self.assertEquals(options.tab_name_align, 'center') self.assertEquals(options.tab_name_align, 'center')
self.assertEquals(options.tab_side, 'left') self.assertEquals(options.tab_side, 'left')
domdiv.calculate_layout(options) domdiv.calculate_layout(options)
self.assertEquals(options.tab_name_align, 'centre') # check for change in value self.assertEquals(options.tab_name_align,
self.assertEquals(options.tab_side, 'left') 'centre') # check for change in value
self.assertEquals(options.tab_side, 'left')