diff --git a/decode.py b/decode.py index 9d16e94..c89e2c4 100755 --- a/decode.py +++ b/decode.py @@ -1,12 +1,9 @@ -#!c:/Python27/python.exe -u #!/usr/bin/env python import sys import os import zipfile import shutil -#to use: py decode.py homebrew.txt homepretty.txt --norarity -v -mse in mtgencode folder. - libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib') sys.path.append(libdir) import utils @@ -19,7 +16,8 @@ def exclude_sets(cardset): return cardset == 'Unglued' or cardset == 'Unhinged' or cardset == 'Celebration' def main(fname, oname = None, verbose = True, - gatherer = False, for_forum = False, creativity = False, norarity = False, for_mse = False): + gatherer = False, for_forum = False, for_mse = False, + creativity = False, norarity = False): cards = [] valid = 0 invalid = 0 @@ -113,11 +111,18 @@ def main(fname, oname = None, verbose = True, def writecards(writer): if for_mse: - # have to prepend a massive chunk. + # have to prepend a massive chunk of formatting info writer.write(utils.mse_prepend) for card in cards: - writer.write((card.format(gatherer = gatherer, for_forum = for_forum, for_mse = for_mse))) - if creativity and not for_mse: # this won't end well if mse mode is enabled. + if for_mse: + writer.write(card.to_mse().encode('utf-8')) + else: + writer.write(card.format(gatherer = gatherer, + for_forum = for_forum).encode('utf-8')) + + if creativity: + if for_mse: + writer.write('\tnotes:\n\t\t'.encode('utf-8')) writer.write('~~ closest cards ~~\n'.encode('utf-8')) nearest = cbow.nearest(card) for dist, cardname in nearest: @@ -133,8 +138,10 @@ def main(fname, oname = None, verbose = True, cardname = '[card]' + cardname + '[/card]' writer.write((cardname + ': ' + str(dist) + '\n').encode('utf-8')) writer.write('\n'.encode('utf-8')) + if for_mse: - writer.write('version control:\n\ttype: none\napprentice code: ') # have to append some junk at the end of file. + # more formatting info + writer.write('version control:\n\ttype: none\napprentice code: ') if oname: if verbose: @@ -142,16 +149,21 @@ def main(fname, oname = None, verbose = True, with open(oname, 'w') as ofile: writecards(ofile) if for_mse: - shutil.copyfile(oname, 'set') # copy whatever output file is produced, name the copy 'set' (yes, no extension). - zf = zipfile.ZipFile(oname+'.mse-set', mode='w') # use the freaky mse extension instead of zip. - try: - zf.write('set') # zip up the set file into oname.mse-set. - finally: - print 'Made an MSE set file called ' + oname + '.mse-set.' - zf.close() - os.remove('set') # the set file is useless outside the .mse-set, delete it. - - + # Copy whatever output file is produced, name the copy 'set' (yes, no extension). + if os.path.isfile('set'): + print 'ERROR: tried to overwrite existing file "set" - aborting.' + return + shutil.copyfile(oname, 'set') + # Use the freaky mse extension instead of zip. + with zipfile.ZipFile(oname+'.mse-set', mode='w') as zf: + try: + # Zip up the set file into oname.mse-set. + zf.write('set') + finally: + if verbose: + print 'Made an MSE set file called ' + oname + '.mse-set.' + # The set file is useless outside the .mse-set, delete it. + os.remove('set') else: writecards(sys.stdout) sys.stdout.flush() @@ -179,6 +191,6 @@ if __name__ == '__main__': args = parser.parse_args() main(args.infile, args.outfile, verbose = args.verbose, - gatherer = args.gatherer, for_forum = args.forum, creativity = args.creativity, - norarity = args.norarity, for_mse = args.mse) + gatherer = args.gatherer, for_forum = args.forum, for_mse = args.mse, + creativity = args.creativity, norarity = args.norarity) exit(0) diff --git a/lib/cardlib.py b/lib/cardlib.py index 0d5b17c..4b88cb7 100644 --- a/lib/cardlib.py +++ b/lib/cardlib.py @@ -1,12 +1,10 @@ # card representation -# -*- coding: utf-8 import re import random import utils import transforms from manalib import Manacost, Manatext -from titlecase import titlecase # Some text prettification stuff that people may not have installed try: @@ -19,6 +17,11 @@ try: import textwrap import nltk.data sent_tokenizer = nltk.data.load('tokenizers/punkt/english.pickle') + # This could me made smarter - MSE will capitalize for us after :, + # but we still need to capitalize the first english component of an activation + # cost that starts with symbols, such as {2U}, *R*emove a +1/+1 counter from @: etc. + def cap(s): + return s[:1].capitalize() + s[1:] # This crazy thing is actually invoked as an unpass, so newlines are still # encoded. def sentencecase(s): @@ -28,11 +31,26 @@ try: for line in lines: if line: sentences = sent_tokenizer.tokenize(line) - clines += [' '.join([sent.capitalize() for sent in sentences])] + clines += [' '.join([cap(sent) for sent in sentences])] return utils.newline.join(clines).replace(utils.reserved_marker, utils.x_marker) except ImportError: + # non-nltk implementation provided by PAK90 + def uppercaseNewLineAndFullstop(string): + # ok, let's capitalize every letter after a full stop and newline. + # first let's find all indices of '.' and '\n' + indices = [0] # initialise with 0, since we always want to capitalise the first letter. + newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers). + for i in range (len(string)): + if string[i] == '\\': + indices.append(i + 1) # we want the index of the letter after the \n, so add one. + newlineIndices.append(i + 1) + if string[i] == '.' or string[i] == "=": # also handle the choice bullets. + indices.append(i + 2) # we want the index of the letter after the ., so we need to count the space as well. + indexSet = set(indices) # convert it to a set for the next part; the capitalisation. + return "".join(c.upper() if i in indexSet else c for i, c in enumerate(string)) + def sentencecase(s): - return s + return uppercaseNewLineAndFullstop(s) # These are used later to determine what the fields of the Card object are called. # Define them here because they have nothing to do with the actual format. @@ -112,20 +130,6 @@ def fields_check_valid(fields): return not field_pt in fields -def uppercaseNewLineAndFullstop(string): - # ok, let's capitalize every letter after a full stop and newline. - # first let's find all indices of '.' and '\n' - indices = [0] # initialise with 0, since we always want to capitalise the first letter. - newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers). - for i in range (len(string)): - if string[i] == '\n': - indices.append(i + 1) # we want the index of the letter after the \n, so add one. - newlineIndices.append(i + 1) - if string[i] == '.' or string[i] == "=": # also handle the choice bullets. - indices.append(i + 2) # we want the index of the letter after the ., so we need to count the space as well. - indexSet = set(indices) # convert it to a set for the next part; the capitalisation. - return "".join(c.upper() if i in indexSet else c for i, c in enumerate(string)) - # These functions take a bunch of source data in some format and turn # it into nicely labeled fields that we know how to initialize a card from. # Both return a dict that maps field names to lists of possible values, @@ -623,7 +627,7 @@ class Card: outstr += '[/i]' outstr += '\n' - elif for_forum: + else: cardname = self.__dict__[field_name] outstr += cardname if self.__dict__[field_rarity]: @@ -674,106 +678,117 @@ class Card: outstr += '<' + str(idx) + '> ' + str(value) outstr += '\n' - - elif for_mse: - # need a 'card' string first - outstr += 'card:\n' - cardname = titlecase(self.__dict__[field_name]) - outstr += '\tname: ' + cardname + '\n' - if self.__dict__[field_rarity]: - if self.__dict__[field_rarity] in utils.json_rarity_unmap: - rarity = utils.json_rarity_unmap[self.__dict__[field_rarity]] - else: - rarity = self.__dict__[field_rarity] - outstr += '\trarity: ' + rarity.lower() + '\n' - #if not self.parsed: - # outstr += ' _UNPARSED_' - #if not self.valid: - # outstr += ' _INVALID_' - - if "land" not in self.__dict__[field_types]: - outstr += '\tcasting cost: ' + self.__dict__[field_cost].format(for_forum = for_forum).replace('{','').replace('}','') - outstr += '\n' - - outstr += '\tsuper type: ' + ' '.join(self.__dict__[field_supertypes] + self.__dict__[field_types]).title() + '\n' - #outstr += 'sub type: ' + ' '.join(self.__dict__[field_types]) - if self.__dict__[field_subtypes]: - outstr += '\tsub type: ' + ' '.join(self.__dict__[field_subtypes]).title() - outstr += '\n' - - if self.__dict__[field_text].text: - mtext = self.__dict__[field_text].text - mtext = transforms.text_unpass_1_choice(mtext, delimit = False) - mtext = transforms.text_unpass_2_counters(mtext) - mtext = transforms.text_unpass_3_unary(mtext) - mtext = transforms.text_unpass_4_symbols(mtext, for_forum) - mtext = transforms.text_unpass_5_cardname(mtext, cardname) - mtext = transforms.text_unpass_6_newlines(mtext) - newtext = Manatext('') - newtext.text = mtext - newtext.costs = self.__dict__[field_text].costs - newtext = newtext.format(for_forum = for_forum) - newtext = newtext.replace(utils.this_marker, cardname) # first let's put the cardname where all the @s are. - newtext = newtext.replace(utils.counter_rename + ".", "countered.") # then replace any 'uncast' at the end of a sentence with 'countered'. - newtext = newtext.replace(utils.dash_marker, "—") # also replace the ~ with a — for choices. - newtext = newtext.replace(utils.counter_rename, "counter") # then replace all the mid-sentence 'uncast' with 'counter'. - newtext = newtext.replace('{','').replace('}','') # now we encase mana/tap symbols with the correct tags for mse. - linecount = newtext.count('\n') + 1 # adding 1 because no newlines means 1 line, 1 newline means 2 lines etc. - - newtext = uppercaseNewLineAndFullstop(newtext) # make all the things uppercase! - - # done after uppercasing everything because string[i] == • doesn't work apparently. - newtext = newtext.replace(utils.bullet_marker, "•") # replace the = with a •. - - newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers). - for i in range (len(newtext)): - if newtext[i] == '\n': - newlineIndices.append(i + 1) - - # need to do Special Things if it's a planeswalker. - if "planeswalker" in str(self.__dict__[field_types]): # for some reason this is in types, not supertypes... - outstr += '\tstylesheet: m15-planeswalker\n' # set the proper card style for a 3-line walker. - - # set up the loyalty cost fields using regex to find how many there are. - i = 0 - for costs in re.findall('[-+]\d?\d: ', newtext): # regex handles 2-figure loyalty costs. - i += 1 - outstr += '\tloyalty cost ' + str(i) + ': ' + costs + '\n' - # sub out the loyalty costs. - newtext = re.sub('[-+]\d?\d: ', '', newtext) - - newtext = uppercaseNewLineAndFullstop(newtext) # we need to uppercase again; previous uppercase call didn't work due to loyalty costs being there. - - if self.__dict__[field_loyalty]: - outstr += '\tloyalty: ' + utils.from_unary(self.__dict__[field_loyalty]) + '\n' - - # have to do special snowflake stuff for rule text with more than 1 line. 2 or more lines need to be double-indented... - if linecount == 1: - outstr += '\trule text: ' + newtext + '\n' - elif linecount > 1: - newtext = newtext.replace('\n','\n\t\t') - outstr += '\trule text:\n\t\t' + newtext + '\n' - - # also uncast still exists at this point? weird. should be 'unpassed' apparently. until then, did a manual replace. - - if self.__dict__[field_pt]: - ptstring = utils.from_unary(self.__dict__[field_pt]).split('/') - if (len(ptstring) > 1): #really don't want to be accessing anything nonexistent. - outstr += '\tpower: ' + ptstring[0] + '\n' - outstr += '\ttoughness: ' + ptstring[1] + '\n' - #outstr += '\n' - - # now append all the other useless fields that the setfile expects. - outstr += '\thas styling: false\n\tnotes:\n\ttime created:2015-07-20 22:53:07\n\ttime modified:2015-07-20 22:53:08\n\textra data:\n\timage:\n\tcard code text:\n\tcopyright:\n\timage 2:\n\tcopyright 2: ' - - #print outstr - - if self.bside and not for_mse: + if self.bside: outstr += utils.dash_marker * 8 + '\n' outstr += self.bside.format(gatherer = gatherer, for_forum = for_forum) return outstr + def to_mse(self): + outstr = '' + + # need a 'card' string first + outstr += 'card:\n' + + cardname = titlecase(self.__dict__[field_name]) + outstr += '\tname: ' + cardname + '\n' + + if self.__dict__[field_rarity]: + if self.__dict__[field_rarity] in utils.json_rarity_unmap: + rarity = utils.json_rarity_unmap[self.__dict__[field_rarity]] + else: + rarity = self.__dict__[field_rarity] + outstr += '\trarity: ' + rarity.lower() + '\n' + #if not self.parsed: + # outstr += ' _UNPARSED_' + #if not self.valid: + # outstr += ' _INVALID_' + + if not self.__dict__[field_cost].none: + outstr += '\tcasting cost: ' + self.__dict__[field_cost].format().replace('{','').replace('}','') + outstr += '\n' + + outstr += '\tsuper type: ' + ' '.join(self.__dict__[field_supertypes] + + self.__dict__[field_types]).title() + '\n' + if self.__dict__[field_subtypes]: + outstr += '\tsub type: ' + ' '.join(self.__dict__[field_subtypes]).title() + '\n' + + if self.__dict__[field_text].text: + mtext = self.__dict__[field_text].text + mtext = transforms.text_unpass_1_choice(mtext, delimit = False) + mtext = transforms.text_unpass_2_counters(mtext) + mtext = transforms.text_unpass_3_unary(mtext) + mtext = transforms.text_unpass_4_symbols(mtext, False) + mtext = sentencecase(mtext) + # I don't really want these MSE specific passes in transforms, + # but they could be pulled out separately somewhere else in here. + mtext = mtext.replace(utils.this_marker, '' + + utils.this_marker + '') + mtext = transforms.text_unpass_5_cardname(mtext, cardname) + mtext = transforms.text_unpass_6_newlines(mtext) + newtext = Manatext('') + newtext.text = mtext + newtext.costs = self.__dict__[field_text].costs + newtext = newtext.format() + + #NOT NEEDED newtext = newtext.replace(utils.this_marker, cardname) # first let's put the cardname where all the @s are. + + + # newtext = newtext.replace(utils.counter_rename + ".", "countered.") # then replace any 'uncast' at the end of a sentence with 'countered'. + # newtext = newtext.replace(utils.dash_marker, u'\u2014') # also replace the ~ with a u2014 for choices. + # newtext = newtext.replace(utils.counter_rename, "counter") # then replace all the mid-sentence 'uncast' with 'counter'. + # newtext = newtext.replace('{','').replace('}','') # now we encase mana/tap symbols with the correct tags for mse. + # linecount = newtext.count('\n') + 1 # adding 1 because no newlines means 1 line, 1 newline means 2 lines etc. + + # newtext = sentencecase(newtext) # make all the things uppercase! + + # # done after uppercasing everything because string[i] == u2022 doesn't work apparently. + # newtext = newtext.replace(utils.bullet_marker, u'\u2022') # replace the = with a u2022. + + # used later + linecount = newtext.count('\n') + 1 # adding 1 because no newlines means 1 line, 1 newline means 2 lines etc. + + # actually really important + newtext = newtext.replace('{','').replace('}','') # now we encase mana/tap symbols with the correct tags for mse. + + newlineIndices = [0] # also need to keep track of pure newlines (for planeswalkers). + for i in range (len(newtext)): + if newtext[i] == '\n': + newlineIndices.append(i + 1) + + # need to do Special Things if it's a planeswalker. + if "planeswalker" in str(self.__dict__[field_types]): # for some reason this is in types, not supertypes... + outstr += '\tstylesheet: m15-planeswalker\n' # set the proper card style for a 3-line walker. + + # set up the loyalty cost fields using regex to find how many there are. + i = 0 + lcost_regex = r'[-+]?\d+: ' # 1+ figures, might be 0. + for costs in re.findall(lcost_regex, newtext): + i += 1 + outstr += '\tloyalty cost ' + str(i) + ': ' + costs + '\n' + # sub out the loyalty costs. + newtext = re.sub(lcost_regex, '', newtext) + + #newtext = sentencecase(newtext) # we need to uppercase again; previous uppercase call didn't work due to loyalty costs being there. + + if self.__dict__[field_loyalty]: + outstr += '\tloyalty: ' + utils.from_unary(self.__dict__[field_loyalty]) + '\n' + + newtext = newtext.replace('\n','\n\t\t') + outstr += '\trule text:\n\t\t' + newtext + '\n' + + if self.__dict__[field_pt]: + ptstring = utils.from_unary(self.__dict__[field_pt]).split('/') + if (len(ptstring) > 1): #really don't want to be accessing anything nonexistent. + outstr += '\tpower: ' + ptstring[0] + '\n' + outstr += '\ttoughness: ' + ptstring[1] + '\n' + #outstr += '\n' + + # now append all the other useless fields that the setfile expects. + outstr += '\thas styling: false\n\tnotes:\n\ttime created:2015-07-20 22:53:07\n\ttime modified:2015-07-20 22:53:08\n\textra data:\n\timage:\n\tcard code text:\n\tcopyright:\n\timage 2:\n\tcopyright 2: ' + + return outstr + def vectorize(self): ld = '(' rd = ')' diff --git a/lib/titlecase.py b/lib/titlecase.py deleted file mode 100644 index 7751797..0000000 --- a/lib/titlecase.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -titlecase.py v0.2 -Original Perl version by: John Gruber http://daringfireball.net/ 10 May 2008 -Python version by Stuart Colville http://muffinresearch.co.uk -License: http://www.opensource.org/licenses/mit-license.php -""" - -import unittest -import sys -import re - - -SMALL = 'a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v\.?|via|vs\.?' -PUNCT = "[!\"#$%&'‘()*+,-./:;?@[\\\\\\]_`{|}~]" - -SMALL_WORDS = re.compile(r'^(%s)$' % SMALL, re.I) -INLINE_PERIOD = re.compile(r'[a-zA-Z][.][a-zA-Z]') -UC_ELSEWHERE = re.compile(r'%s*?[a-zA-Z]+[A-Z]+?' % PUNCT) -CAPFIRST = re.compile(r"^%s*?([A-Za-z])" % PUNCT) -SMALL_FIRST = re.compile(r'^(%s*)(%s)\b' % (PUNCT, SMALL), re.I) -SMALL_LAST = re.compile(r'\b(%s)%s?$' % (SMALL, PUNCT), re.I) -SUBPHRASE = re.compile(r'([:.;?!][ ])(%s)' % SMALL) - -def titlecase(text): - - """ - Titlecases input text - - This filter changes all words to Title Caps, and attempts to be clever - about *un*capitalizing SMALL words like a/an/the in the input. - - The list of "SMALL words" which are not capped comes from - the New York Times Manual of Style, plus 'vs' and 'v'. - - """ - - words = re.split('\s', text) - line = [] - for word in words: - if INLINE_PERIOD.search(word) or UC_ELSEWHERE.match(word): - line.append(word) - continue - if SMALL_WORDS.match(word): - line.append(word.lower()) - continue - line.append(CAPFIRST.sub(lambda m: m.group(0).upper(), word)) - - line = " ".join(line) - - line = SMALL_FIRST.sub(lambda m: '%s%s' % ( - m.group(1), - m.group(2).capitalize() - ), line) - - line = SMALL_LAST.sub(lambda m: m.group(0).capitalize(), line) - - line = SUBPHRASE.sub(lambda m: '%s%s' % ( - m.group(1), - m.group(2).capitalize() - ), line) - - return line - -class TitlecaseTests(unittest.TestCase): - - """Tests to ensure titlecase follows all of the rules""" - - def test_q_and_a(self): - """Testing: Q&A With Steve Jobs: 'That's What Happens In Technology' """ - text = titlecase( - "Q&A with steve jobs: 'that's what happens in technology'" - ) - result = "Q&A With Steve Jobs: 'That's What Happens in Technology'" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_at_and_t(self): - """Testing: What Is AT&T's Problem?""" - - text = titlecase("What is AT&T's problem?") - result = "What Is AT&T's Problem?" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_apple_deal(self): - """Testing: Apple Deal With AT&T Falls Through""" - - text = titlecase("Apple deal with AT&T falls through") - result = "Apple Deal With AT&T Falls Through" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_this_v_that(self): - """Testing: this v that""" - text = titlecase("this v that") - result = "This v That" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_this_v_that2(self): - """Testing: this v. that""" - - text = titlecase("this v. that") - result = "This v. That" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_this_vs_that(self): - """Testing: this vs that""" - - text = titlecase("this vs that") - result = "This vs That" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_this_vs_that2(self): - """Testing: this vs. that""" - - text = titlecase("this vs. that") - result = "This vs. That" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_apple_sec(self): - """Testing: The SEC's Apple Probe: What You Need to Know""" - - text = titlecase("The SEC's Apple Probe: What You Need to Know") - result = "The SEC's Apple Probe: What You Need to Know" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_small_word_quoted(self): - """Testing: 'by the Way, Small word at the start but within quotes.'""" - - text = titlecase( - "'by the Way, small word at the start but within quotes.'" - ) - result = "'By the Way, Small Word at the Start but Within Quotes.'" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_small_word_end(self): - """Testing: Small word at end is nothing to be afraid of""" - - text = titlecase("Small word at end is nothing to be afraid of") - result = "Small Word at End Is Nothing to Be Afraid Of" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_sub_phrase_small_word(self): - """Testing: Starting Sub-Phrase With a Small Word: a Trick, Perhaps?""" - - text = titlecase( - "Starting Sub-Phrase With a Small Word: a Trick, Perhaps?" - ) - result = "Starting Sub-Phrase With a Small Word: A Trick, Perhaps?" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_small_word_quotes(self): - """Testing: Sub-Phrase With a Small Word in Quotes: 'a Trick...""" - - text = titlecase( - "Sub-Phrase With a Small Word in Quotes: 'a Trick, Perhaps?'" - ) - result = "Sub-Phrase With a Small Word in Quotes: 'A Trick, Perhaps?'" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_small_word_double_quotes(self): - """Testing: Sub-Phrase With a Small Word in Quotes: \"a Trick...""" - text = titlecase( - 'Sub-Phrase With a Small Word in Quotes: "a Trick, Perhaps?"' - ) - result = 'Sub-Phrase With a Small Word in Quotes: "A Trick, Perhaps?"' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_nothing_to_be_afraid_of(self): - """Testing: \"Nothing to Be Afraid of?\"""" - text = titlecase('"Nothing to Be Afraid of?"') - result = '"Nothing to Be Afraid Of?"' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_nothing_to_be_afraid_of2(self): - """Testing: \"Nothing to Be Afraid Of?\"""" - - text = titlecase('"Nothing to be Afraid Of?"') - result = '"Nothing to Be Afraid Of?"' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_a_thing(self): - """Testing: a thing""" - - text = titlecase('a thing') - result = 'A Thing' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_vapourware(self): - """Testing: 2lmc Spool: 'Gruber on OmniFocus and Vapo(u)rware'""" - text = titlecase( - "2lmc Spool: 'gruber on OmniFocus and vapo(u)rware'" - ) - result = "2lmc Spool: 'Gruber on OmniFocus and Vapo(u)rware'" - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_domains(self): - """Testing: this is just an example.com""" - text = titlecase('this is just an example.com') - result = 'This Is Just an example.com' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_domains2(self): - """Testing: this is something listed on an del.icio.us""" - - text = titlecase('this is something listed on del.icio.us') - result = 'This Is Something Listed on del.icio.us' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_itunes(self): - """Testing: iTunes should be unmolested""" - - text = titlecase('iTunes should be unmolested') - result = 'iTunes Should Be Unmolested' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_thoughts_on_music(self): - """Testing: Reading Between the Lines of Steve Jobs’s...""" - - text = titlecase( - 'Reading between the lines of steve jobs’s ‘thoughts on music’' - ) - result = 'Reading Between the Lines of Steve Jobs’s ‘Thoughts on '\ - 'Music’' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_repair_perms(self): - """Testing: Seriously, ‘Repair Permissions’ Is Voodoo""" - - text = titlecase('seriously, ‘repair permissions’ is voodoo') - result = 'Seriously, ‘Repair Permissions’ Is Voodoo' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - def test_generalissimo(self): - """Testing: Generalissimo Francisco Franco...""" - - text = titlecase( - 'generalissimo francisco franco: still dead; kieren McCarthy: '\ - 'still a jackass' - ) - result = 'Generalissimo Francisco Franco: Still Dead; Kieren '\ - 'McCarthy: Still a Jackass' - self.assertEqual(text, result, "%s should be: %s" % (text, result, )) - - -if __name__ == '__main__': - if not sys.stdin.isatty(): - for line in sys.stdin: - print titlecase(line) - - else: - suite = unittest.TestLoader().loadTestsFromTestCase(TitlecaseTests) - unittest.TextTestRunner(verbosity=2).run(suite) -