def test_card_type_checkers(self): """Check the various utilities for checking card type and properties.""" self.maxDiff = None oDob = IAbstractCard(u"L\xe1z\xe1r Dobrescu") self.assertTrue(is_vampire(oDob)) self.assertTrue(is_crypt_card(oDob)) self.assertFalse(is_trifle(oDob)) oAbo = IAbstractCard('Abombwe') self.assertFalse(is_vampire(oAbo)) self.assertFalse(is_crypt_card(oAbo)) self.assertTrue(is_trifle(oAbo)) oAshur = IAbstractCard('Ashur Tablets') self.assertFalse(is_vampire(oAshur)) self.assertFalse(is_crypt_card(oAshur)) self.assertFalse(is_trifle(oAshur)) oEarl = IAbstractCard(u'Earl "Shaka74" Deams') self.assertFalse(is_vampire(oEarl)) self.assertTrue(is_crypt_card(oEarl)) self.assertFalse(is_trifle(oEarl)) oOssian = IAbstractCard('Ossian') self.assertFalse(is_vampire(oOssian)) self.assertFalse(is_crypt_card(oOssian)) self.assertFalse(is_trifle(oOssian))
def _setup_cardlists(self, aSelectedCards): """Extract the needed card info from the model""" aAllAbsCards = [IAbstractCard(oCard) for oCard in self._get_all_cards()] iCryptSize = 0 iLibrarySize = 0 self.dSelectedCounts = {} self.iSelectedCount = 0 # Initialise dict 1st, as cards with a count of 0 in the selection # are possible. for oCard in aSelectedCards: self.dSelectedCounts.setdefault(oCard, 0) for oCard in aAllAbsCards: if is_crypt_card(oCard): iCryptSize += 1 else: iLibrarySize += 1 if oCard in self.dSelectedCounts: self.dSelectedCounts[oCard] += 1 self.iSelectedCount += 1 # The assumption is that the user is interested in all copies of # the selected cards (as it seems the most useful), so we treat # the selection of any instance of the card in the list as # selecting all of them if self.bCrypt: self.iTotal = iCryptSize else: self.iTotal = iLibrarySize
def _update_printing(self, oPrinting, dPrintInfo): """Update the specific printing with the required info""" # Clear any existing properties (to ensure we reflect # updates correctly) for oProp in oPrinting.properties: oPrinting.removePrintingProperty(oProp) # Add properties for the variant sDate = dPrintInfo.pop('date') sBack = dPrintInfo.pop('back') oDateProp = self._oMaker.make_printing_property("Release Date: %s" % sDate) oBackProp = self._oMaker.make_printing_property("Back Type: %s" % sBack) # pylint: disable=no-member # SQLObject confuses pylint oPrinting.addPrintingProperty(oDateProp) oPrinting.addPrintingProperty(oBackProp) # pylint: enable=no-member aCards = dPrintInfo.pop('cards', []) # Create Physical cards for the variant cards if needed for sCardName in aCards: oAbsCard = IAbstractCard(sCardName) _oCard = self._oMaker.make_physical_card(oAbsCard, oPrinting) # Any other items in the dict get added 'as-is' for sKey, sValue in dPrintInfo.items(): oProp = self._oMaker.make_printing_property("%s: %s" % (sKey, sValue)) oPrinting.addProperty(oProp)
def _group_cards(self, aCards, iNum, aSubSets, bSuperior, bUseCardSet): """Group the cards and return only cards with iNum or more instances. This works because of our database structure and query, which ends up returning a match for each discipline in the discipline filter that matches.""" aDistinct = set(aCards) dResults = {} aDistinct.remove(self.oSelCard) # Don't match ourselves bVampire = is_vampire(self.oSelCard) if bUseCardSet: aCardSetCards = set([IAbstractCard(x) for x in self.model.get_card_iterator( self.model.get_current_filter())]) else: aCardSetCards = None for oCard in list(aDistinct): if aCards.count(oCard) < iNum: aDistinct.remove(oCard) elif bUseCardSet and oCard not in aCardSetCards: # Remove cards not in the view from the results aDistinct.remove(oCard) dResults['all'] = aDistinct for oCard in aDistinct: aFullSet = _make_superset(oCard, bSuperior, bVampire) for aSet in aSubSets: # We only add the card if it has all elements of the set if aSet.issubset(aFullSet): dResults.setdefault(make_key(aSet, bSuperior), []).append(oCard) return dResults
def make_set_3(): """Copy of the second card set with Abebe dropped""" aAddedPhysCards = get_phys_cards() oPhysCardSet3 = PhysicalCardSet(name=CARD_SET_NAMES[2]) oPhysCardSet3.comment = ('A formatted test comment\nA second line\n' 'A third line') oPhysCardSet3.author = 'A test author' oPhysCardSet3.annotations = 'Some Annotations' for iLoop in range(5, 10): # pylint: disable=no-member # SQLObect confused pylint oPC = aAddedPhysCards[iLoop] if IAbstractCard(oPC).name == 'Abebe (Group 4)': continue oPhysCardSet3.addPhysicalCard(oPC.id) for sName, sExpansion, iCount in SET_2_ONLY_CARDS: # pylint: disable=no-member # SQLObect confused pylint oPC = make_card(sName, sExpansion) for _iNum in range(iCount): oPhysCardSet3.addPhysicalCard(oPC.id) for sName, sExpansion, iCount in SET_3_ONLY_CARDS: # pylint: disable=no-member # SQLObect confused pylint oPC = make_card(sName, sExpansion) for _iNum in range(iCount): oPhysCardSet3.addPhysicalCard(oPC.id) oPhysCardSet3.syncUpdate() return oPhysCardSet3
def setUpClass(cls): """Setup some useful constants for the test cases""" cls.aCards = list(AbstractCard.select()) cls.oSwallowed = IAbstractCard("Swallowed by the Night") cls.oAshur = IAbstractCard("Ashur Tablets") cls.oPath = IAbstractCard("The Path of Blood") cls.oAire = IAbstractCard("Aire of Elation") cls.oAabbt = IAbstractCard("Aabbt Kindred") cls.oEarl = IAbstractCard('Earl "Shaka74" Deams') cls.oShaEnnu = IAbstractCard("Sha-Ennu") cls.oRaven = IAbstractCard("Raven Spy") cls.oNewBlood = IAbstractCard("New Blood")
def make_abstract_card(self, sCard): try: return IAbstractCard(sCard) except SQLObjectNotFound: sName = sCard.strip() sCanonical = sName.lower() return SutekhAbstractCard(canonicalName=sCanonical, name=sName, text="")
def _gen_inv(self, oHolder): """Process the card set, creating the lines as needed""" aUnique = make_unique_names() dCards = {'Crypt': {}, 'Library': {}} sResult = "" for oCard in oHolder.cards: sType = type_of_card(IAbstractCard(oCard)) sName = lackey_name(IAbstractCard(oCard), aUnique) dCards[sType].setdefault(sName, 0) dCards[sType][sName] += 1 # Sort the output # Need to be in this order for sType in ['Library', 'Crypt']: for sName, iNum in sorted(dCards[sType].items()): sResult += '%d\t%s\n' % (iNum, sName) if sType == 'Library': sResult += 'Crypt:\n' return sResult
def find_twda(self, _oWidget, sMode): """Find decks which match the given search""" # Only want the distinct cards - numbers are unimportant aAbsCards = set(self._get_selected_abs_cards()) if not aAbsCards: do_complaint_error('Need to select some cards for this plugin') return if len(aAbsCards) > 20: do_complaint_error('Too many cards selected (%d). Please select ' 'no more than 20 cards' % len(aAbsCards)) return aCardFilters = [] iTotCards = len(aAbsCards) for oCard in aAbsCards: aCardFilters.append(SpecificCardFilter(oCard)) # needs to be OR, since we're matching against the card to card set # mapping table oCardFilter = FilterOrBox(aCardFilters) aNames = self._get_twda_names() oMapFilter = MultiPhysicalCardSetMapFilter(aNames) oFullFilter = FilterAndBox([oCardFilter, oMapFilter]) # pylint: disable=no-member # SQLObject confuses pylint dCardSets = {} for oMapCard in oFullFilter.select(MapPhysicalCardToPhysicalCardSet): oCS = oMapCard.physicalCardSet sCardName = IAbstractCard(oMapCard).name dCardSets.setdefault(oCS, {}) dCardSets[oCS].setdefault(sCardName, 0) dCardSets[oCS][sCardName] += 1 if sMode == 'all' and iTotCards > 1: # This is a little clunky, but, because of how we construct the # filters, we currently have the any match set, so we need to # filter this down to those that match all the cards for oCS in list(dCardSets): if len(dCardSets[oCS]) != iTotCards: # Not all, so drop this one del dCardSets[oCS] sCards = '", "'.join(sorted([x.name for x in aAbsCards])) if sMode == 'any': sMatchText = 'Matching ANY of "%s"' % sCards else: sMatchText = 'Matching ALL of "%s"' % sCards # Create a dialog showing the results if dCardSets: oDlg = self._fill_dlg(dCardSets, sMatchText) else: oDlg = self._empty_dlg(sMatchText) oDlg.set_default_size(700, 600) oDlg.show_all() oDlg.show()
def add_row(oTBody, iCount, sName): """Add a row to the display table""" oCard = IAbstractCard(sName) oTR = SubElement(oTBody, "tr") oTD = SubElement(oTR, "td") _add_span(oTD, '%dx' % iCount, 'tablevalue') oTD = SubElement(oTR, "td") oSpan = SubElement(oTD, "span") oSpan.attrib["class"] = "tablevalue" self._gen_link(oCard, oSpan, sName, False)
def _get_cards(self, oCardIter): """Create the dictionary of cards given the list of cards""" dDict = {} for oCard in oCardIter: oPhysCard = IPhysicalCard(oCard) oAbsCard = IAbstractCard(oCard) sSet = self._get_ardb_exp_name(oPhysCard) dDict.setdefault((oAbsCard, sSet), 0) dDict[(oAbsCard, sSet)] += 1 return dDict
def test_find_vamps(self): """Test functions for finding base/adv vampires.""" oAlanBase = IAbstractCard('Alan Sovereign (Group 3)') oNewBlood = IAbstractCard('New Blood') oAlanAdv = IAbstractCard('Alan Sovereign (Group 3) (Advanced)') self.assertEqual(find_base_vampire(oAlanAdv), oAlanBase) self.assertEqual(find_adv_vampire(oAlanBase), oAlanAdv) self.assertEqual(find_adv_vampire(oNewBlood), None) # These aren't real vampires, but allows us to test the # storyline logic oAlanAdv = FakeCard('Alan Sovereign (EC 2013) (Advanced)') self.assertEqual(find_base_vampire(oAlanAdv), oAlanBase) oAlanAdv = FakeCard('Alan Sovereign (Red Sign) (Advanced)') self.assertEqual(find_base_vampire(oAlanAdv), oAlanBase) oAlanAdv = FakeCard('Alan Sovereign (Ascension of Caine) (Advanced)') self.assertEqual(find_base_vampire(oAlanAdv), oAlanBase)
def find_adv_vampire(oVampire): """Find the corresponding advanced vampire Returns None if the vampre cannout be found.""" sAdvName = oVampire.name + ' (Advanced)' # Note that base Brunhilde links to the non-storyline advanced version try: return IAbstractCard(sAdvName) except SQLObjectNotFound: return None
def _make_base_map(self): """Find all the vampires with advanced versions.""" aAllAdvanced = list(SutekhAbstractCard.selectBy(level='advanced')) for oAbsCard in aAllAdvanced: sBaseName = oAbsCard.name.replace(' (Advanced)', '') try: oBaseCard = IAbstractCard(sBaseName) self._aBaseVamps.add(oBaseCard) except SQLObjectNotFound: # we skip the special cases here continue
def test_adapters(self): """Extra sanity checks on the adapaters.""" self.maxDiff = None for oAdapter in (IAbstractCard, IPhysicalCard, IExpansion, IRarity, IRarityPair, ICardType, IArtist, IKeyword): self.assertRaises(NotImplementedError, oAdapter, 1) self.assertRaises(NotImplementedError, oAdapter, None) # Various pass through tests self.assertEqual(IAbstractCard("Ossian"), IAbstractCard(IAbstractCard("Ossian"))) oExp = IExpansion("KMW") self.assertEqual(oExp, IExpansion(oExp)) oPrinting = IPrinting((oExp, None)) self.assertEqual(oPrinting, IPrinting(oPrinting)) oPhysCard = IPhysicalCard((IAbstractCard("Ossian"), oPrinting)) self.assertEqual(oPhysCard, IPhysicalCard(oPhysCard)) self.assertEqual(oPhysCard.abstractCard, IAbstractCard("Ossian")) self.assertEqual(oPhysCard.abstractCard, IAbstractCard(oPhysCard)) self.assertEqual(IArtist("Lawrence Snelly"), IArtist(IArtist("Lawrence Snelly"))) self.assertEqual(IKeyword('not for legal play'), IKeyword(IKeyword('not for legal play'))) self.assertEqual(IRarity("Common"), IRarity(IRarity("Common"))) self.assertEqual(IRarityPair(("EK", "Common")), IRarityPair(IRarityPair(("EK", "Common")))) self.assertEqual(ICardType("Vampire"), ICardType(ICardType("Vampire")))
def begin_print(self, oPrintOp, _oContext): """Set up printing context. This includes determining pagination and the number of pages. """ self._aMissing = set() oPrintOp.set_unit(Gtk.Units.POINTS) oPrintOp.set_n_pages(1) oIter = self.model.get_card_iterator(self.model.get_current_filter()) aCards = sorted([IPhysicalCard(x) for x in oIter], key=lambda y: IAbstractCard(y).name) # We lookup all the images here, so we can cancel before printing # if we're missing images. for oTheCard in aCards: oCard = oTheCard if self._ePrintExpansion == PrintExpOption.PRINT_LATEST: # We build a fake card with the correct expansion sLatestPrinting = get_printing_info(oTheCard.abstractCard)[0] oExp = IPrinting(sLatestPrinting) oCard = IPhysicalCard((oTheCard.abstractCard, oExp)) sFilename = self._oImageFrame.lookup_filename(oCard)[0] if not check_file(sFilename): bOk = False for sExpName in get_printing_info(oTheCard.abstractCard): oPrinting = IPrinting(sExpName) oCard = IPhysicalCard((oTheCard.abstractCard, oPrinting)) sFilename = self._oImageFrame.lookup_filename(oCard)[0] if check_file(sFilename): bOk = True self._aFiles.append(sFilename) break if not bOk: self._aMissing.add(oTheCard.abstractCard.name) # Move onto the next card continue else: self._aFiles.append(sFilename) if self._aMissing: # Abort the print operation oPrintOp.cancel() return # We put 9 images on a page iNumCards = len(aCards) iNumPages = iNumCards // 9 # Add extra page if needed for the excess cards if iNumPages * 9 < iNumCards: iNumPages += 1 oPrintOp.set_n_pages(iNumPages)
def _get_ardb_exp_name(self, oPhysCard): """Extract the correct ARDB name for the expansion""" if oPhysCard.printing: oExpansion = oPhysCard.printing.expansion else: oAbsCard = IAbstractCard(oPhysCard) # ARDB doesn't have a concept of 'No expansion', so we # need to fake it. We use the first legitimate expansion # We sort the list to ensure stable results across databases, etc. aExp = sorted([oP.expansion for oP in oAbsCard.rarity], key=lambda x: x.shortname) oExpansion = aExp[0] sSet = escape_ardb_expansion_name(oExpansion) return sSet
def _find_card(self, sTitle): """Find the abstract card this rules applies to.""" sTitle = self._oMasterOut.sub('', sTitle) sTitle = self._oCommaThe.sub('', sTitle) try: return IAbstractCard(sTitle) except SQLObjectNotFound: pass try: return IAbstractCard(self._dOddTitles[sTitle]) except KeyError: pass except SQLObjectNotFound: pass try: return IAbstractCard(('The ' + sTitle)) except SQLObjectNotFound: pass return None
def activate(self, _oWidget): """Create the actual dialog, and populate it""" oFilter = self.model.get_current_filter() aCards = [ IAbstractCard(oCard) for oCard in self.model.get_card_iterator(oFilter) ] oDialog = RandomPromoDialog(self.parent, aCards) oDialog.set_size_request(450, 600) oDialog.show_all() oDialog.run() oDialog.destroy()
def _verify_database(self): """Check that the database is correctly populated""" try: _oCard = IAbstractCard('Ossian') except SQLObjectNotFound: # Log error so verbose picks it up logging.warning('Ossian not found in the database') # Inform the user iResponse = do_complaint( 'Database is missing cards. Try import the cardlist now?', Gtk.MessageType.ERROR, Gtk.ButtonsType.YES_NO, False) if iResponse == Gtk.ResponseType.YES: self.do_refresh_card_list() # Create object cache self.__oSutekhObjectCache = SutekhObjectCache()
def find_base_vampire(oVampire): """Find the corresponding base vampire. Returns None if the vampire cannot be found.""" sBaseName = oVampire.name.replace(' (Advanced)', '') # Special cases if '(EC 2013)' in sBaseName: sBaseName = sBaseName.replace(' (EC 2013)', '') if '(Red Sign)' in sBaseName: sBaseName = sBaseName.replace(' (Red Sign)', '') if '(Ascension of Caine)' in sBaseName: sBaseName = sBaseName.replace(' (Ascension of Caine)', '') try: return IAbstractCard(sBaseName) except SQLObjectNotFound: return None
def _add_library_text(self, oCardText, aSortedLibCards): """Add the text of the library cards to the tree.""" def gen_requirements(oCard): """Extract the requirements from the card""" oList = Element("ul") # Clan requirements aClan = [x.name for x in oCard.clan] if aClan: oListItem = SubElement(oList, "li") _add_span(oListItem, 'Requires:', 'label') _add_span(oListItem, "/".join(aClan), 'requirement') # Cost if oCard.costtype is not None: oListItem = SubElement(oList, "li") _add_span(oListItem, 'Cost:', 'label') _add_span(oListItem, "%d %s" % (oCard.cost, oCard.costtype), 'cost') # Disciplines sDisciplines = self._gen_disciplines(oCard) if sDisciplines != "": oListItem = SubElement(oList, "li") _add_span(oListItem, 'Disciplines:', 'label') _add_span(oListItem, sDisciplines, 'disciplines') return oList for sType, aList in aSortedLibCards: oTypeHead = SubElement(oCardText, "h4") oTypeHead.attrib["class"] = "libraryttype" oTypeHead.text = sType for sName in sorted([x[1] for x in aList[1:]]): oCard = IAbstractCard(sName) oCardHead = SubElement(oCardText, "h5") oCardHead.attrib["class"] = "cardname" oCardHead.text = sName oReqList = gen_requirements(oCard) # pylint: disable=len-as-condition # ElementTree is special, and and using bool to check # for children is officially deprecated. if len(oReqList): # not empty, so add oCardText.append(oReqList) # Text _add_text(oCardText, oCard)
def _gen_inv(self, oHolder): """Process the card set, creating the lines as needed""" dCards = {} aSeen = set() sResult = "" for oCard in AbstractCard.select(): dCards[oCard] = 0 for oCard in oHolder.cards: oAbsCard = IAbstractCard(oCard) dCards[oAbsCard] += 1 # We sort to ensure we process multi-group cards in the right order for oCard in sorted(dCards, key=lambda x: x.name): iNum = dCards[oCard] sName = norm_name(oCard) # FIXME: It's not clear if ELDB is still being developed enough # to support the multi-group vampires, but we try this anyway if sName in aSeen and is_crypt_card(oCard): sName = f'{sName} (Group {oCard.group})' aSeen.add(sName) sResult += '"%s",%d,0,"","%s"\n' % (sName, iNum, type_of_card(oCard)) return sResult
def tabulate(self, aCards): """Create a table from the list of (or iterator over) cards. Returns the table which is a nested list where each element is a row and each row consists of column values. The rows are in the same order as the cards in aCards. The columns are in the same order as in the aColNames list passed to __init__. """ aColFuncs = [self._dPropFuncs[x] for x in self._aColNames] aTable = [] for oCard in aCards: oCard = IAbstractCard(oCard) aRow = [] for fProp in aColFuncs: aRow.append(fProp(oCard)) aTable.append(aRow) return aTable
def main_with_args(aTheArgs): """ Main function: Loop through the options and process the database accordingly. """ # Turn off some pylint refactoring warnings # pylint: disable=too-many-statements, too-many-branches # pylint: disable=too-many-return-statements, too-many-locals oOptParser, (oOpts, aArgs) = parse_options(aTheArgs) sPrefsDir = prefs_dir(SutekhInfo.NAME) oLogHandler = StreamHandler(sys.stdout) if len(aArgs) != 1: oOptParser.print_help() return 1 if oOpts.db is None: ensure_dir_exists(sPrefsDir) oOpts.db = sqlite_uri(os.path.join(sPrefsDir, "sutekh.db")) bDoCardListChecks = False oConn = connectionForURI(oOpts.db) sqlhub.processConnection = oConn if oOpts.sql_debug: oConn.debug = True if not oConn.tableExists('abstract_card'): if not oOpts.refresh_tables: print("Database has not been created.") return 1 else: try: _oCard = IAbstractCard('Ossian') except SQLObjectNotFound: if not oOpts.fetch and oOpts.ww_file is None: print("Database is missing cards - please import the cardlist") return 1 # Only log critical messages by default setup_logging(oOpts.verbose) if oOpts.reload: if not oOpts.refresh_tables: print("reload should be called with --refresh-tables") return 1 sTempdir = gen_temp_dir() (fTemp, sReloadZipName) = \ tempfile.mkstemp('.zip', 'sutekh', sTempdir) os.close(fTemp) oZipFile = ZipFileWrapper(sReloadZipName) oZipFile.do_dump_all_to_zip(oLogHandler) # We dump the databases here # We will reload them later if oOpts.refresh_ruling_tables: if not refresh_tables([Ruling], sqlhub.processConnection): print("refresh failed") return 1 if oOpts.refresh_tables: if not refresh_tables(TABLE_LIST, sqlhub.processConnection): print("refresh failed") return 1 if oOpts.refresh_physical_card_tables: if not refresh_tables(PHYSICAL_LIST, sqlhub.processConnection): print("refresh failed") return 1 if oOpts.lookup_file is not None: read_lookup_data(EncodedFile(oOpts.lookup_file), oLogHandler) if oOpts.ww_file is not None: read_white_wolf_list(EncodedFile(oOpts.ww_file), oLogHandler) bDoCardListChecks = True if oOpts.extra_file is not None: read_white_wolf_list(EncodedFile(oOpts.extra_file), oLogHandler) bDoCardListChecks = True if oOpts.exp_data_file is not None: read_exp_info_file(EncodedFile(oOpts.exp_data_file), oLogHandler) if oOpts.ruling_file is not None: read_rulings(EncodedFile(oOpts.ruling_file), oLogHandler) if oOpts.fetch: read_lookup_data(EncodedFile(LOOKUP_DATA_URL, True), oLogHandler) read_white_wolf_list(EncodedFile(WW_CARDLIST_URL, True), oLogHandler) read_rulings(EncodedFile(WW_RULINGS_URL, True), oLogHandler) read_white_wolf_list(EncodedFile(EXTRA_CARD_URL, True), oLogHandler) read_exp_info_file(EncodedFile(EXP_DATA_URL, True), oLogHandler) bDoCardListChecks = True if bDoCardListChecks: # Run the consistency checks on the database for oAbsCard in AbstractCard.select(): aMessages = do_card_checks(oAbsCard) if aMessages: print('\n'.join(aMessages)) if oOpts.upgrade_db: oDBUpgrade = DBUpgradeManager() oDBUpgrade.attempt_database_upgrade(oLogHandler) if oOpts.save_all_css and oOpts.save_cs is not None: print("Can't use --save-cs and --save-all-cs Simulatenously") return 1 # initialise the caches, so adapters, etc work for reading / writing # card sets make_adapter_caches() if oOpts.read_physical_cards_from is not None: oFile = PhysicalCardXmlFile(oOpts.read_physical_cards_from) oFile.read() if oOpts.save_all_css: write_all_pcs() if oOpts.dump_zip_name is not None: oZipFile = ZipFileWrapper(oOpts.dump_zip_name) oZipFile.do_dump_all_to_zip(oLogHandler) if oOpts.restore_zip_name is not None: oZipFile = ZipFileWrapper(oOpts.restore_zip_name) oZipFile.do_restore_from_zip(oLogHandler=oLogHandler) if oOpts.save_cs is not None: oFile = PhysicalCardSetXmlFile(oOpts.cs_filename) oFile.write(oOpts.save_cs) if oOpts.print_cs is not None: try: oCS = IPhysicalCardSet(oOpts.print_cs) fPrint = StringIO() oPrinter = WriteArdbText() oPrinter.write(fPrint, CardSetWrapper(oCS)) print(fPrint.getvalue()) except SQLObjectNotFound: print('Unable to load card set', oOpts.print_cs) return 1 if oOpts.list_cs: if not print_card_list(oOpts.limit_list): return 1 elif oOpts.limit_list is not None: print("Can't use limit-list-to without list-cs") return 1 if oOpts.filter_string is not None: dResults = run_filter(oOpts.filter_string, oOpts.filter_cs) print_card_filter_list(dResults, print_card_details, oOpts.filter_detailed) if oOpts.print_card is not None: if not do_print_card(oOpts.print_card, print_card_details): return 1 if oOpts.read_cs is not None: oFile = PhysicalCardSetXmlFile(oOpts.read_cs) oFile.read() if oOpts.read_acs is not None: oFile = AbstractCardSetXmlFile(oOpts.read_acs) oFile.read() if oOpts.reload: oZipFile = ZipFileWrapper(sReloadZipName) oZipFile.do_restore_from_zip(oLogHandler=oLogHandler) os.remove(sReloadZipName) os.rmdir(sTempdir) if oOpts.upgrade_db and oOpts.refresh_tables: print("Can't use --upgrade-db and --refresh-tables simulatenously") return 1 return 0
def test_basic(self): """Basic WW list parser tests""" # pylint: disable=too-many-statements, too-many-locals # Want a long, sequential test case to minimise repeated setups self.maxDiff = None # Check that we've added the 'last updated' date entry oToday = datetime.date.today() self.assertEqual(get_metadata_date(CARDLIST_UPDATE_DATE), oToday) aCards = sorted(list(AbstractCard.select()), key=lambda oC: oC.name) # Check card names self.assertEqual(len(aCards), len(self.aExpectedCards)) self.assertEqual([oC.name for oC in aCards], self.aExpectedCards) # Check Magnum # pylint: disable=invalid-name # o44 is OK here o44 = IAbstractCard(".44 Magnum") self.assertEqual(o44.canonicalName, u".44 magnum") self.assertEqual(o44.name, u".44 Magnum") self.assertTrue(o44.text.startswith(u"Weapon, gun.\n2R")) self.assertTrue(o44.text.endswith(u"each combat.")) self.assertEqual(o44.group, None) self.assertEqual(o44.capacity, None) self.assertEqual(o44.cost, 2) self.assertEqual(o44.life, None) self.assertEqual(o44.costtype, 'pool') self.assertEqual(o44.level, None) # pylint: enable=invalid-name oCommon = IRarity('Common') oJyhad = IExpansion('Jyhad') oVTES = IExpansion('VTES') oAnthology = IExpansion('Anthology') self.assertTrue(oCommon in [oP.rarity for oP in o44.rarity]) self.assertTrue(oJyhad in [oP.expansion for oP in o44.rarity]) self.assertTrue(oVTES in [oP.expansion for oP in o44.rarity]) self.assertTrue(oAnthology not in [oP.expansion for oP in o44.rarity]) self.assertTrue(IRarityPair(('VTES', 'Common')) in o44.rarity) self.assertTrue(IKeyword('gun') in o44.keywords) self.assertTrue(IKeyword('weapon') in o44.keywords) # Find some discipline pairs oFortInf = IDisciplinePair((u"Fortitude", u"inferior")) oFortSup = IDisciplinePair((u"Fortitude", u"superior")) oQuiSup = IDisciplinePair((u"Quietus", u"superior")) oCelInf = IDisciplinePair((u"Celerity", u"inferior")) oAusInf = IDisciplinePair((u"Auspex", u"inferior")) oAusSup = IDisciplinePair((u"Auspex", u"superior")) oPreSup = IDisciplinePair((u"Presence", u"superior")) oObfSup = IDisciplinePair((u"Obfuscate", u"superior")) oAboInf = IDisciplinePair((u"Abombwe", u"inferior")) oAboSup = IDisciplinePair((u"Abombwe", u"superior")) oValSup = IDisciplinePair((u'Valeren', u"superior")) # Check Dobrescu oDob = IAbstractCard(u"L\xe1z\xe1r Dobrescu") self.assertEqual(oDob.canonicalName, u"l\xe1z\xe1r dobrescu (group 2)") self.assertEqual(oDob.name, u"L\xe1z\xe1r Dobrescu (Group 2)") self.assertTrue(oDob.text.startswith( u"Independent: L\xe1z\xe1r may move")) self.assertTrue(oDob.text.endswith(u"as a (D) action.")) self.assertEqual(oDob.group, 2) self.assertEqual(oDob.capacity, 3) self.assertEqual(oDob.cost, None) self.assertEqual(oDob.life, None) self.assertEqual(oDob.costtype, None) self.assertEqual(oDob.level, None) self.assertTrue(IClan('Ravnos') in oDob.clan) self.assertEqual(len(oDob.discipline), 1) self.assertTrue(oFortInf in oDob.discipline) self.assertEqual(len(oDob.cardtype), 1) self.assertTrue(ICardType('Vampire') in oDob.cardtype) self.assertTrue(ISect('Independent') in oDob.sect) self.assertEqual(len(oDob.artists), 1) self.assertTrue(IArtist('Rebecca Guay') in oDob.artists) self.assertEqual(len(oDob.rulings), 1) oRuling = oDob.rulings[0] self.assertTrue(oRuling.text.startswith("Cannot use his special")) self.assertTrue(oRuling.text.endswith("uncontrolled region.")) self.assertEqual(oRuling.code, "[LSJ 19990215]") # Check Ashur Tablets oAshur = IAbstractCard('Ashur Tablets') self.assertTrue(oAnthology in [oP.expansion for oP in oAshur.rarity]) self.assertTrue(IRarityPair(('Anthology', 'Fixed')) in oAshur.rarity) # Check Abstract and Physical expansions match for oAbs in AbstractCard.select(): aExps = [oPair.expansion for oPair in oAbs.rarity] for oExp in aExps: try: oPrint = IPrinting((oExp, None)) _oPair = IPhysicalCard((oAbs, oPrint)) except SQLObjectNotFound: # pragma: no cover # We don't except to hit this during testing. self.fail(f"Missing physical card {oAbs.name}" f" from expansion {oExp.name}") # Check Yvette oYvette = IAbstractCard(u"Yvette, The Hopeless") self.assertEqual(oYvette.canonicalName, u"yvette, the hopeless (group 3)") self.assertEqual(oYvette.name, u"Yvette, The Hopeless (Group 3)") self.assertTrue(oYvette.text.startswith("Camarilla.")) self.assertEqual(oYvette.group, 3) self.assertEqual(oYvette.capacity, 3) self.assertEqual(oYvette.cost, None) self.assertEqual(oYvette.life, None) self.assertEqual(oYvette.costtype, None) self.assertEqual(oYvette.level, None) self.assertTrue(IClan('Toreador') in oYvette.clan) self.assertEqual(len(oYvette.clan), 1) self.assertEqual(len(oYvette.discipline), 2) self.assertTrue(oFortInf not in oYvette.discipline) self.assertTrue(oCelInf in oYvette.discipline) self.assertTrue(oAusInf in oYvette.discipline) self.assertEqual(len(oYvette.cardtype), 1) self.assertTrue(ICardType('Vampire') in oYvette.cardtype) self.assertTrue(ISect('Camarilla') in oYvette.sect) self.assertEqual(len(oYvette.artists), 1) self.assertTrue(IArtist('Leif Jones') in oYvette.artists) # Check Sha-Ennu oShaEnnu = IAbstractCard(u"Sha-Ennu") self.assertEqual(oShaEnnu.canonicalName, u"sha-ennu (group 4)") self.assertEqual(oShaEnnu.name, u"Sha-Ennu (Group 4)") self.assertTrue(oShaEnnu.text.startswith("Sabbat regent:")) self.assertTrue(oShaEnnu.text.endswith("+2 bleed.")) self.assertEqual(oShaEnnu.group, 4) self.assertEqual(oShaEnnu.capacity, 11) self.assertEqual(oShaEnnu.cost, None) self.assertEqual(oShaEnnu.life, None) self.assertEqual(oShaEnnu.costtype, None) self.assertEqual(oShaEnnu.level, None) self.assertTrue(IClan('Tzimisce') in oShaEnnu.clan) self.assertEqual(len(oShaEnnu.clan), 1) self.assertEqual(len(oShaEnnu.discipline), 6) self.assertTrue(oAusSup in oShaEnnu.discipline) self.assertTrue(oAusInf not in oShaEnnu.discipline) self.assertEqual(len(oShaEnnu.cardtype), 1) self.assertTrue(ICardType('Vampire') in oShaEnnu.cardtype) self.assertTrue(ISect('Sabbat') in oShaEnnu.sect) self.assertTrue(ITitle('Regent') in oShaEnnu.title) self.assertTrue(IRarityPair(('Third', 'Vampire')) in oShaEnnu.rarity) self.assertFalse(IRarityPair(('VTES', 'Common')) in oShaEnnu.rarity) self.assertFalse(IRarityPair(('VTES', 'Vampire')) in oShaEnnu.rarity) self.assertEqual(len(oShaEnnu.artists), 1) self.assertTrue(IArtist('Richard Thomas') in oShaEnnu.artists) self.assertTrue(IKeyword('0 stealth') in oShaEnnu.keywords) self.assertTrue(IKeyword('0 intercept') in oShaEnnu.keywords) self.assertTrue(IKeyword('1 strength') in oShaEnnu.keywords) self.assertTrue(IKeyword('3 bleed') in oShaEnnu.keywords) oShaEnnu2 = IAbstractCard(u"Sha-Ennu (Group 4)") self.assertEqual(oShaEnnu2.id, oShaEnnu.id) # Check Kabede oKabede = IAbstractCard(u"Kabede Maru") self.assertEqual(oKabede.canonicalName, u"kabede maru (group 5)") self.assertEqual(oKabede.name, u"Kabede Maru (Group 5)") self.assertTrue(oKabede.text.startswith("Laibon magaji:")) self.assertTrue(oKabede.text.endswith("affect Kabede.)")) self.assertEqual(oKabede.group, 5) self.assertEqual(oKabede.capacity, 9) self.assertEqual(oKabede.cost, None) self.assertEqual(oKabede.life, None) self.assertEqual(oKabede.costtype, None) self.assertEqual(oKabede.level, None) self.assertTrue(IClan('Banu Haqim') in oKabede.clan) self.assertEqual(len(oKabede.clan), 1) self.assertEqual(len(oKabede.discipline), 6) self.assertTrue(oAusSup in oKabede.discipline) self.assertTrue(oQuiSup in oKabede.discipline) self.assertTrue(oAboInf in oKabede.discipline) self.assertTrue(oAboSup not in oKabede.discipline) self.assertEqual(len(oKabede.cardtype), 1) self.assertTrue(ICardType('Vampire') in oKabede.cardtype) self.assertTrue(ISect('Laibon') in oKabede.sect) self.assertTrue(ITitle('Magaji') in oKabede.title) self.assertTrue(IRarityPair(('LotN', 'Uncommon')) in oKabede.rarity) self.assertEqual(len(oKabede.artists), 1) self.assertTrue(IArtist('Ken Meyer, Jr.') in oKabede.artists) self.assertTrue(IKeyword('0 stealth') in oKabede.keywords) self.assertTrue(IKeyword('0 intercept') in oKabede.keywords) self.assertTrue(IKeyword('1 strength') in oKabede.keywords) self.assertTrue(IKeyword('1 bleed') in oKabede.keywords) # Check Predator's Communion oPredComm = IAbstractCard(u"Predator's Communion") self.assertEqual(oPredComm.canonicalName, u"predator's communion") self.assertEqual(oPredComm.name, u"Predator's Communion") self.assertTrue(oPredComm.text.startswith("[abo] [REFLEX]")) self.assertTrue(oPredComm.text.endswith("unlocks.")) self.assertEqual(oPredComm.group, None) self.assertEqual(oPredComm.capacity, None) self.assertEqual(oPredComm.cost, None) self.assertEqual(oPredComm.life, None) self.assertEqual(oPredComm.costtype, None) self.assertEqual(oPredComm.level, None) self.assertEqual(len(oPredComm.discipline), 1) self.assertTrue(oAboSup in oPredComm.discipline) self.assertEqual(len(oPredComm.cardtype), 2) self.assertTrue(ICardType('Reaction') in oPredComm.cardtype) self.assertTrue(ICardType('Reflex') in oPredComm.cardtype) self.assertTrue(IRarityPair(('LoB', 'Common')) in oPredComm.rarity) self.assertEqual(len(oPredComm.artists), 1) self.assertTrue(IArtist('David Day') in oPredComm.artists) # Check Earl oEarl = IAbstractCard(u'Earl "Shaka74" Deams') self.assertEqual(oEarl.canonicalName, u'earl "shaka74" deams (group 4)') self.assertEqual(oEarl.name, u'Earl "Shaka74" Deams (Group 4)') self.assertTrue(oEarl.text.startswith("Earl gets +1 stealth")) self.assertTrue(oEarl.text.endswith("[1 CONVICTION].")) self.assertEqual(oEarl.group, 4) self.assertEqual(oEarl.capacity, None) self.assertEqual(oEarl.cost, None) self.assertEqual(oEarl.life, 6) self.assertEqual(oEarl.costtype, None) self.assertEqual(oEarl.level, None) self.assertTrue(ICreed('Visionary') in oEarl.creed) self.assertEqual(len(oEarl.creed), 1) self.assertEqual(len(oEarl.virtue), 3) self.assertTrue(IVirtue('Martyrdom') in oEarl.virtue) self.assertTrue(IVirtue('Judgment') in oEarl.virtue) self.assertTrue(IVirtue('Vision') in oEarl.virtue) self.assertEqual(len(oEarl.cardtype), 1) self.assertTrue(ICardType('Imbued') in oEarl.cardtype) self.assertTrue(IRarityPair(('NoR', 'Uncommon')) in oEarl.rarity) self.assertEqual(len(oEarl.artists), 1) self.assertTrue(IArtist('David Day') in oEarl.artists) # Check Aire oAire = IAbstractCard("Aire of Elation") self.assertEqual(oAire.canonicalName, u"aire of elation") self.assertEqual(oAire.name, u"Aire of Elation") self.assertTrue(oAire.text.startswith("You cannot play another")) self.assertTrue(oAire.text.endswith("is Toreador.")) self.assertEqual(oAire.group, None) self.assertEqual(oAire.capacity, None) self.assertEqual(oAire.cost, 1) self.assertEqual(oAire.life, None) self.assertEqual(oAire.costtype, 'blood') self.assertEqual(oAire.level, None) self.assertEqual(len(oAire.discipline), 1) self.assertTrue(oPreSup in oAire.discipline) self.assertEqual(len(oAire.cardtype), 1) self.assertTrue(ICardType("Action Modifier") in oAire.cardtype) self.assertTrue(IRarityPair(('DS', 'Common')) in oAire.rarity) self.assertTrue(IRarityPair(('FN', 'Precon')) in oAire.rarity) self.assertTrue(IRarityPair(('CE', 'Common')) in oAire.rarity) self.assertTrue(IRarityPair(('CE', 'Precon')) in oAire.rarity) self.assertTrue(IRarityPair(('Anarchs', 'Precon')) in oAire.rarity) self.assertTrue(IRarityPair(('KMW', 'Precon')) in oAire.rarity) self.assertEqual(len(oAire.artists), 1) self.assertTrue(IArtist('Greg Simanson') in oAire.artists) # Abjure oAbjure = IAbstractCard("Abjure") self.assertEqual(oAbjure.canonicalName, u"abjure") self.assertEqual(oAbjure.name, u"Abjure") self.assertTrue(oAbjure.text.startswith("[COMBAT] Lock this")) self.assertTrue(oAbjure.text.endswith("or ash heap.")) self.assertEqual(oAbjure.group, None) self.assertEqual(oAbjure.capacity, None) self.assertEqual(oAbjure.cost, None) self.assertEqual(oAbjure.life, None) self.assertEqual(oAbjure.costtype, None) self.assertEqual(oAbjure.level, None) self.assertEqual(len(oAbjure.virtue), 1) self.assertTrue(IVirtue('Redemption') in oAbjure.virtue) self.assertEqual(len(oAbjure.cardtype), 1) self.assertTrue(ICardType('Power') in oAbjure.cardtype) self.assertEqual(len(oAbjure.artists), 1) self.assertTrue(IArtist('Brian LeBlanc') in oAbjure.artists) # Abombwe Master Card oAbo = IAbstractCard('Abombwe') self.assertEqual(oAbo.canonicalName, 'abombwe') self.assertEqual(oAbo.name, 'Abombwe') self.assertTrue(oAbo.text.startswith("Master: Discipline. Trifle")) self.assertTrue(oAbo.text.endswith("superior Abombwe.")) self.assertEqual(oAbo.group, None) self.assertEqual(oAbo.capacity, 1) self.assertEqual(oAbo.cost, None) self.assertEqual(oAbo.life, None) self.assertEqual(oAbo.costtype, None) self.assertEqual(oAbo.level, None) self.assertEqual(len(oAbo.discipline), 0) self.assertEqual(len(oAbo.cardtype), 1) self.assertTrue(ICardType('Master') in oAbo.cardtype) self.assertEqual(len(oAbo.rulings), 0) self.assertEqual(len(oAbo.artists), 1) self.assertTrue(IArtist('Ken Meyer, Jr.') in oAbo.artists) self.assertTrue(IKeyword('trifle') in oAbo.keywords) self.assertTrue(IKeyword('discipline') in oAbo.keywords) # Ablative Skin Card oAblat = IAbstractCard('Ablative Skin') self.assertEqual(oAblat.canonicalName, 'ablative skin') self.assertEqual(oAblat.name, 'Ablative Skin') self.assertTrue(oAblat.text.startswith("+1 stealth action")) self.assertTrue(oAblat.text.endswith("damage in combat in this way.")) self.assertEqual(oAblat.group, None) self.assertEqual(oAblat.cost, None) self.assertEqual(oAblat.life, None) self.assertEqual(oAblat.costtype, None) self.assertEqual(oAblat.level, None) self.assertEqual(len(oAblat.discipline), 1) self.assertTrue(oFortSup in oAblat.discipline) self.assertEqual(len(oAblat.cardtype), 1) self.assertTrue(ICardType('Action') in oAblat.cardtype) self.assertEqual(len(oAblat.rulings), 1) oRuling = oAblat.rulings[0] self.assertTrue(oRuling.text.startswith("Cannot be used to prevent")) self.assertTrue(oRuling.text.endswith("Blood Fury).")) self.assertEqual(oRuling.code, "[LSJ 19990216]") self.assertEqual(len(oAblat.artists), 1) self.assertTrue(IArtist('Richard Thomas') in oAblat.artists) # Check Independent titles oAmbrig = IAbstractCard(u"Ambrogino Giovanni") self.assertTrue(ITitle('Independent with 1 vote') in oAmbrig.title) oAmisa = IAbstractCard(u"Amisa") self.assertTrue(ITitle('Independent with 2 votes') in oAmisa.title) # Check Kemintiri oKemintiri = IAbstractCard(u"Kemintiri (Advanced)") self.assertEqual(oKemintiri.canonicalName, u"kemintiri (group 2) (advanced)") self.assertEqual(oKemintiri.name, u"Kemintiri (Group 2) (Advanced)") self.assertTrue(oKemintiri.text.startswith("Advanced, Independent.")) self.assertEqual(oKemintiri.group, 2) self.assertEqual(oKemintiri.capacity, 10) self.assertEqual(oKemintiri.cost, None) self.assertEqual(oKemintiri.life, None) self.assertEqual(oKemintiri.costtype, None) self.assertEqual(oKemintiri.level, 'advanced') self.assertTrue(IKeyword('advanced') in oKemintiri.keywords) self.assertTrue(IClan('Ministry') in oKemintiri.clan) self.assertEqual(len(oKemintiri.clan), 1) self.assertEqual(len(oKemintiri.discipline), 6) self.assertTrue(oAusInf in oKemintiri.discipline) self.assertTrue(oObfSup in oKemintiri.discipline) self.assertTrue(oPreSup in oKemintiri.discipline) self.assertEqual(len(oKemintiri.cardtype), 1) self.assertTrue(ICardType('Vampire') in oKemintiri.cardtype) self.assertTrue(ISect('Independent') in oKemintiri.sect) self.assertEqual(len(oKemintiri.artists), 1) self.assertTrue(IArtist('Lawrence Snelly') in oKemintiri.artists) # Make sure we're not picking up the Merged title self.assertEqual(len(oKemintiri.title), 0) self.assertTrue(IRarityPair(('KMW', 'Uncommon')) in oKemintiri.rarity) # Check lookups for sLookup in ["Kemintiri (Adv)", "Kemintiri (ADV)", "Kemintiri (Group 2) (Adv)", "Kemintiri (Group 2) (ADV)", "Kemintiri (Advanced) (Group 2)", "Kemintiri (Adv) (Group 2)", "Kemintiri (ADV) (Group 2)"]: oKem2 = IAbstractCard(sLookup) self.assertEqual(oKem2.id, oKemintiri.id) # Check ANY group handling oNewBlood = IAbstractCard('New Blood') self.assertEqual(oNewBlood.group, -1) self.assertEqual(oNewBlood.capacity, 2) self.assertEqual(oNewBlood.life, None) self.assertEqual(oNewBlood.cost, None) self.assertTrue(IClan('Blood Brother') in oNewBlood.clan) self.assertEqual(len(oNewBlood.clan), 1) self.assertEqual(len(oNewBlood.discipline), 1) self.assertTrue('belongs to the chosen circle.' in oNewBlood.text) # Check The Path oPath1 = IAbstractCard('The Path of Blood') self.assertTrue(IClan('Banu Haqim') in oPath1.clan) self.assertEqual(oPath1.cost, 1) self.assertEqual(oPath1.costtype, 'pool') self.assertTrue(ICardType('Master') in oPath1.cardtype) self.assertTrue(IKeyword('unique') in oPath1.keywords) # Check alternative lookup oPath2 = IAbstractCard('Path of Blood, The') self.assertEqual(oPath1.id, oPath2.id) # Check The Slaughterhouse oSlaughter = IAbstractCard('The Slaughterhouse') self.assertEqual(oSlaughter.canonicalName, u"the slaughterhouse") self.assertEqual(len(oSlaughter.keywords), 2) self.assertTrue(IKeyword('burn option') in oSlaughter.keywords) self.assertTrue(IKeyword('location') in oSlaughter.keywords) # Check keywords for The Ankara Citadel, Turkey oCitadel = IAbstractCard('The Ankara Citadel, Turkey') self.assertEqual(oCitadel.cost, 2) self.assertTrue(IClan('Tremere') in oCitadel.clan) self.assertEqual(oCitadel.costtype, 'blood') self.assertTrue(IKeyword('location') in oCitadel.keywords) self.assertTrue(IKeyword('unique') in oCitadel.keywords) # Check life & keywords for Ossian oOssian = IAbstractCard('Ossian') self.assertEqual(oOssian.life, 4) self.assertEqual(oOssian.cost, 3) self.assertEqual(oOssian.costtype, 'pool') self.assertTrue(IKeyword('werewolf') in oOssian.keywords) self.assertTrue(IKeyword('red list') in oOssian.keywords) self.assertTrue(IKeyword('unique') in oOssian.keywords) self.assertTrue(IKeyword('0 bleed') in oOssian.keywords) self.assertTrue(IKeyword('2 strength') in oOssian.keywords) # Check life & keywords for Raven Spy oRaven = IAbstractCard('Raven Spy') self.assertTrue(IKeyword('animal') in oRaven.keywords) self.assertTrue(IKeyword('1 strength') not in oRaven.keywords) self.assertEqual(oRaven.life, 1) self.assertEqual(oRaven.cost, 1) self.assertEqual(oRaven.costtype, 'blood') # Check slave keywords for Fidus and Sheela Na Gig oFidus = IAbstractCard(u"Fidus, The Shrunken Beast") self.assertTrue(IKeyword('tremere slave') in oFidus.keywords) oSheela = IAbstractCard(u"Sheela Na Gig") self.assertTrue(IKeyword('tremere antitribu slave') in oSheela.keywords) # Check for Anarch sect status oAlab = IAbstractCard(u"Alabástrom") self.assertTrue(ISect('Anarch') in oAlab.sect) # Check special cases oRetainer = IAbstractCard('Ghoul Retainer') self.assertTrue(IKeyword('1 strength') in oRetainer.keywords) oHighTop = IAbstractCard('High Top') self.assertTrue(IKeyword('1 intercept') in oHighTop.keywords) oGypsies = IAbstractCard('Gypsies') self.assertTrue(IKeyword('1 stealth') in oGypsies.keywords) # Check brace normalisation self.assertTrue('{strength' in oGypsies.text) self.assertTrue('{mortal' in oGypsies.text) self.assertTrue('-{' not in oGypsies.text) # check brace filtering self.assertTrue('{' not in oGypsies.search_text) oRebekka = IAbstractCard('Rebekka, Chantry Elder of Munich') self.assertTrue(IKeyword('1 stealth') in oRebekka.keywords) oProtracted = IAbstractCard('Protracted Investment') self.assertTrue(IKeyword('investment') in oProtracted.keywords) oBravo = IAbstractCard('Bravo') self.assertTrue(IKeyword('archetype') in oBravo.keywords) oDramatic = IAbstractCard('Dramatic Upheaval') self.assertTrue(IKeyword('not for legal play') in oDramatic.keywords) oMotivated = IAbstractCard('Motivated by Gehenna') self.assertTrue(IKeyword('not for legal play') in oMotivated.keywords) oAaron = IAbstractCard("Aaron's Feeding Razor") self.assertTrue(IKeyword('unique') in oAaron.keywords) # Test adding extra expansions works oAnarchRailroad = IAbstractCard("Anarch Railroad") self.assertEqual(oAnarchRailroad.canonicalName, u"anarch railroad") self.assertEqual(oAnarchRailroad.cost, 2) self.assertEqual(oAnarchRailroad.costtype, 'pool') self.assertTrue(oAnarchRailroad.text.startswith(u"Master: unique")) oAnarchs = IExpansion('Anarchs') oAA = IExpansion('Anarchs and Alastors Storyline') self.assertTrue(oAnarchs in [oP.expansion for oP in oAnarchRailroad.rarity]) self.assertTrue(oAA in [oP.expansion for oP in oAnarchRailroad.rarity]) oAnarchRevolt = IAbstractCard("Anarch Revolt") self.assertEqual(oAnarchRevolt.canonicalName, u"anarch revolt") self.assertEqual(oAnarchRevolt.cost, None) self.assertTrue(oAnarchRevolt.text.startswith(u"Master.")) self.assertTrue(oAnarchs in [oP.expansion for oP in oAnarchRevolt.rarity]) self.assertTrue(oAA in [oP.expansion for oP in oAnarchRevolt.rarity]) self.assertTrue(oJyhad in [oP.expansion for oP in oAnarchRevolt.rarity]) oHtH = IAbstractCard("Hide the Heart") self.assertEqual(oHtH.canonicalName, u"hide the heart") self.assertEqual(len(oHtH.discipline), 2) self.assertTrue(oAusSup in oHtH.discipline) self.assertTrue(oValSup in oHtH.discipline) self.assertEqual(len(oHtH.cardtype), 1) self.assertTrue(ICardType("Reaction") in oHtH.cardtype) self.assertTrue(oHtH.text.startswith('[aus] Reduce')) self.assertTrue(IRarityPair(('HttB', 'Common')) in oHtH.rarity) self.assertTrue(IRarityPair(('Black Chantry', 'Fixed')) in oHtH.rarity) self.assertTrue(IRarityPair(('HttB', 'Precon')) in oHtH.rarity) oSmite = IAbstractCard("Smite") self.assertEqual(oSmite.canonicalName, u"smite") self.assertEqual(oSmite.cost, 3) self.assertEqual(oSmite.costtype, "conviction") self.assertTrue(oSmite.text.startswith('{Strike:}')) # Check for Black Chantry Expansion data oBaronD = IAbstractCard('Baron Dieudonne') oKoT = IExpansion('Keepers of Tradition') oBC = IExpansion('Black Chantry') # Check we handle the conversion of our old name for the Black Chantry # cards correctly oBCold = IExpansion('Black Chantry Reprint') self.assertEqual(oBC, oBCold) self.assertTrue(oKoT in [oP.expansion for oP in oBaronD.rarity]) self.assertTrue(oBC in [oP.expansion for oP in oBaronD.rarity]) # Check that we also pick up the BC expansion for Hide the Heart self.assertTrue(oBC in [oP.expansion for oP in oHtH.rarity]) self.assertFalse(oKoT in [oP.expansion for oP in oHtH.rarity]) # Check we get the rarity for Aye correct oAye = IAbstractCard("Aye") self.assertEqual(oAye.canonicalName, u"aye") oLoB = IExpansion('Legacy of Blood') oEK = IExpansion('EK') # Check some expansion properties while we're here self.assertEqual(oLoB.name, 'Legacy of Blood') self.assertEqual(oLoB.shortname, 'LoB') self.assertEqual(oEK.name, 'Ebony Kingdom') self.assertEqual(oEK.shortname, 'EK') self.assertTrue(oLoB in [oP.expansion for oP in oAye.rarity]) self.assertTrue(oEK in [oP.expansion for oP in oAye.rarity]) self.assertTrue(oCommon in [oP.rarity for oP in oAye.rarity]) # Check that we only got 1 rarity for Aye self.assertEqual(set([oCommon]), set([oP.rarity for oP in oAye.rarity])) self.assertTrue(IRarityPair(('LoB', 'Common')) in oAye.rarity) self.assertTrue(IRarityPair(('EK', 'Common')) in oAye.rarity) # Check that Anarchs Unbound cards have both PDF and kickstart versions oCrow = IAbstractCard("Crow") oPDFDM = IExpansion("Anarchs Unbound") self.assertTrue(oPDFDM.shortname, "AU") oKickstarterDM = IExpansion("Anarchs Unbound (Kickstarter Edition)") self.assertTrue(oPDFDM in [oP.expansion for oP in oCrow.rarity]) self.assertTrue(oKickstarterDM in [oP.expansion for oP in oCrow.rarity]) # ditto Danse Macabre oClaudia = IAbstractCard("Claudia") oPDFDM = IExpansion("Danse Macabre") self.assertTrue(oPDFDM.shortname, "DM") oKickstarterDM = IExpansion("Danse Macabre (Kickstarter Edition)") self.assertTrue(oPDFDM in [oP.expansion for oP in oClaudia.rarity]) self.assertTrue(oKickstarterDM in [oP.expansion for oP in oClaudia.rarity]) # Check The Unaligned pdf oCountJ = IAbstractCard("Count Jocalo") oPDFDM = IExpansion("The Unaligned") self.assertTrue(oPDFDM.shortname, "TU") oKickstarterDM = IExpansion("The Unaligned (Kickstarter Edition)") self.assertTrue(oPDFDM in [oP.expansion for oP in oCountJ.rarity]) self.assertTrue(oKickstarterDM in [oP.expansion for oP in oCountJ.rarity]) # Check the kickstarter on reprinted promos don't have PDF versions oRise = IAbstractCard("Rise of the Fallen") # Must have kickstarter version self.assertTrue(oKickstarterDM in [oP.expansion for oP in oRise.rarity]) # But not PDF self.assertFalse(oPDFDM in [oP.expansion for oP in oRise.rarity]) # Check that we create the correct lookup for Victoria Ash (to group 2) oVicAsh2 = IAbstractCard("Victoria Ash (Group 2)") oVicAsh7 = IAbstractCard("Victoria Ash (Group 7)") oVicAsh = IAbstractCard("Victoria Ash") self.assertNotEqual(oVicAsh2.id, oVicAsh7.id) self.assertEqual(oVicAsh2.id, oVicAsh.id) # Check that we have the Pentex lookups correct # The list checks that we have handled the rename correctly oPentex1 = IAbstractCard('Pentex Subversion') oPentex2 = IAbstractCard('Pentex(TM) Subversion') oPentex3 = IAbstractCard('Pentex™ Subversion') self.assertEqual(oPentex1.id, oPentex2.id) self.assertEqual(oPentex1.id, oPentex3.id)
def test_basic(self): """Set of simple tests of the Card List Model""" # pylint: disable=too-many-statements, too-many-locals # Want a long, sequential test case to minimise # repeated setups, so it has lots of lines + variables oModel = CardListModel(self.oConfig) # We test with illegal cards shown oModel.hideillegal = False oListener = LocalTestListener(oModel, True) self.assertFalse(oListener.bLoadCalled) oModel.load() self.assertTrue(oListener.bLoadCalled) aExpectedCards = set(AbstractCard.select()) self.assertEqual(aExpectedCards, set(oListener.aCards)) self.assertEqual( oModel.get_card_iterator(None).count(), PhysicalCard.select().count()) # The model as an entry for every AbstractCard and entries # below that for every PhysicalCard # Set grouping to None for these tests oModel.groupby = NullGrouping oModel.load() self.assertEqual(count_all_cards(oModel), AbstractCard.select().count()) self.assertEqual(count_second_level(oModel), PhysicalCard.select().count()) # Check without expansions oModel.bExpansions = False oModel.load() self.assertEqual(count_all_cards(oModel), AbstractCard.select().count()) self.assertEqual(count_second_level(oModel), 0) oModel.bExpansions = True oModel.groupby = CryptLibraryGrouping oModel.load() self.assertEqual(count_all_cards(oModel), AbstractCard.select().count()) self.assertEqual(count_second_level(oModel), PhysicalCard.select().count()) self.assertEqual(count_top_level(oModel), 2) # Test filtering # Test filter which selects nothing works oModel.selectfilter = BaseFilters.CardNameFilter('ZZZZZZZ') oModel.applyfilter = True oModel.load() self.assertEqual(count_top_level(oModel), 1) self.assertEqual(count_all_cards(oModel), 0) oModel.applyfilter = False oModel.load() self.assertEqual(count_all_cards(oModel), AbstractCard.select().count()) self.assertEqual(count_second_level(oModel), PhysicalCard.select().count()) self.assertEqual(count_top_level(oModel), 2) # Test card type oModel.selectfilter = BaseFilters.CardTypeFilter('Vampire') oModel.applyfilter = True oModel.load() self.assertEqual(count_top_level(oModel), 1) self.assertEqual(count_second_level(oModel), oModel.get_card_iterator(oModel.selectfilter).count()) oModel.groupby = CardTypeGrouping oModel.load() self.assertEqual(count_top_level(oModel), 1) self.assertEqual(count_second_level(oModel), oModel.get_card_iterator(oModel.selectfilter).count()) # Test path queries # The remain tests require a sorted model oModel.enable_sorting() oPath = '0:0:0' # First expansion for the first card self.assertEqual(oModel.get_exp_name_from_path(oPath), oModel.sUnknownExpansion) self.assertEqual(oModel.get_card_name_from_path(oPath), u'Aabbt Kindred (Group 2)') tAll = oModel.get_all_from_path(oPath) self.assertEqual(tAll[0], u'Aabbt Kindred (Group 2)') self.assertEqual(tAll[1], oModel.sUnknownExpansion) self.assertEqual(tAll[2], 0) self.assertEqual(tAll[3], 2) oIter = oModel.get_iter(oPath) self.assertEqual(oModel.get_child_entries_from_iter(oIter), []) oPath = '0:0' # First card self.assertEqual(oModel.get_exp_name_from_path(oPath), None) self.assertEqual(oModel.get_inc_dec_flags_from_path(oPath), (False, False)) oIter = oModel.get_iter(oPath) tAll = oModel.get_all_from_path(oPath) self.assertEqual(tAll[0], u'Aabbt Kindred (Group 2)') self.assertEqual(tAll[1], None) self.assertEqual(tAll[2], 0) self.assertEqual(tAll[3], 1) oAbbt = IAbstractCard(u'Aabbt Kindred (Group 2)') oFirst = IPhysicalCard((oAbbt, None)) oSecond = IPhysicalCard((oAbbt, IExpansion('Final Nights'))) self.assertEqual(oModel.get_child_entries_from_iter(oIter), [(oFirst, 0), (oSecond, 0)]) # Test that the different variants show correctly oPath = '0:28:0' # Harold's position self.assertEqual(oModel.get_card_name_from_path(oPath), u"Harold Zettler, Pentex Director (Group 4)") self.assertEqual(oModel.get_exp_name_from_path(oPath), oModel.sUnknownExpansion) oPath = '0:28:1' self.assertEqual(oModel.get_card_name_from_path(oPath), u"Harold Zettler, Pentex Director (Group 4)") self.assertEqual(oModel.get_exp_name_from_path(oPath), "Third Edition") oPath = '0:28:2' self.assertEqual(oModel.get_card_name_from_path(oPath), u"Harold Zettler, Pentex Director (Group 4)") self.assertEqual(oModel.get_exp_name_from_path(oPath), "Third Edition (Sketch)") oListener.bLoadCalled = False # Test MessageBus clear does the right thing MessageBus.clear(oModel) oModel.load() self.assertFalse(oListener.bLoadCalled)
def test_basic(self): """Basic card set holder tests.""" # pylint: disable=too-many-statements, too-many-locals # Want a long, sequential test case to minimise repeated setup # Everything is in the database, so should be no problems dSet1 = { '.44 Magnum': [3, None], 'AK-47': [2, 'LotN'], 'Abebe': [3, 'LoB'], 'Abombwe': [3, 'LoB'], 'Abbot': [1, 'Third Edition'], } oCSH = CardSetHolder() aExpectedPrintings = [] for sCardName, aInfo in dSet1.items(): iCnt, sExpName = aInfo oCSH.add(iCnt, sCardName, sExpName, None) if sExpName: oExp = IExpansion(sExpName) oThisPrint = IPrinting((oExp, None)) else: oThisPrint = None aExpectedPrintings.extend([oThisPrint] * iCnt) aExpectedPrintings.sort(key=lambda x: x.id if x else -1) self.assertRaises(RuntimeError, oCSH.create_pcs) oCSH.name = 'Test Set 1' oCSH.create_pcs() oCS = IPhysicalCardSet('Test Set 1') self.assertEqual(len(oCS.cards), 12) oPCSFilter = BaseFilters.PhysicalCardSetFilter('Test Set 1') oAbbotFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.SpecificCardFilter('Abbot')]) aCSCards = [ IAbstractCard(x).name for x in oAbbotFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual(aCSCards, [u'Abbot']) oVampireFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.CardTypeFilter('Vampire')]) aCSCards = [ IAbstractCard(x).name for x in oVampireFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual( aCSCards, [u'Abebe (Group 4)', u'Abebe (Group 4)', u'Abebe (Group 4)']) aPrintings = [oCard.printing for oCard in oCS.cards] aPrintings.sort(key=lambda x: x.id if x else -1) self.assertEqual(aPrintings, aExpectedPrintings) oCSH.name = 'Test Set 2' oCSH.parent = 'Test Set 1' self.assertRaises(RuntimeError, oCSH.remove, 1, 'Abbot', None, None) self.assertRaises(RuntimeError, oCSH.remove, 2, 'Abbot', 'Third Edition', None) oCSH.remove(1, 'Abbot', 'Third Edition', None) oCSH.remove(1, 'Abombwe', 'LoB', None) oCSH.create_pcs() oCS2 = IPhysicalCardSet('Test Set 2') self.assertEqual(oCS2.parent, oCS) self.assertEqual(len(oCS2.cards), 10) oPCSFilter = BaseFilters.PhysicalCardSetFilter('Test Set 2') oAbbotFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.SpecificCardFilter('Abbot')]) aCSCards = [ IAbstractCard(x).name for x in oAbbotFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual(aCSCards, []) oVampireFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.CardTypeFilter('Vampire')]) aCSCards = [ IAbstractCard(x).name for x in oVampireFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual( aCSCards, [u'Abebe (Group 4)', u'Abebe (Group 4)', u'Abebe (Group 4)']) # Misspelt cards - the default lookup should exclude these dSet2 = { '.44 Magnum': [3, None], 'Abede': [3, 'LoB'], } oCSH = CardSetHolder() for sCardName, aInfo in dSet2.items(): iCnt, sExpName = aInfo oCSH.add(iCnt, sCardName, sExpName, None) oCSH.name = 'Test Set 3' oCSH.create_pcs() oCS = IPhysicalCardSet('Test Set 3') self.assertEqual(len(oCS.cards), 3) oPCSFilter = BaseFilters.PhysicalCardSetFilter('Test Set 3') oGunFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.SpecificCardFilter('.44 Magnum')]) aCSCards = [ IAbstractCard(x).name for x in oGunFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual(aCSCards, [u'.44 Magnum', u'.44 Magnum', '.44 Magnum']) oVampireFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.CardTypeFilter('Vampire')]) aCSCards = [ IAbstractCard(x).name for x in oVampireFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual(aCSCards, []) # Misspelt expansions - all cards should be added, but some with # None for the expansion dSet3 = { 'AK-47': [2, 'Lords of the Knight'], 'Abebe': [3, 'Legacy of Bllod'], } oCSH = CardSetHolder() for sCardName, aInfo in dSet3.items(): iCnt, sExpName = aInfo oCSH.add(iCnt, sCardName, sExpName, None) aExpectedPrintings = [None] * 5 # Also check parent warnings oCSH.parent = 'Test Set 5' oCSH.name = 'Test Set 4' self.assertEqual(oCSH.get_parent_pcs(), None) self.assertNotEqual(len(oCSH.get_warnings()), 0) oCSH.clear_warnings() self.assertEqual(len(oCSH.get_warnings()), 0) oCSH.create_pcs() self.assertNotEqual(len(oCSH.get_warnings()), 0) oCS = IPhysicalCardSet('Test Set 4') self.assertEqual(len(oCS.cards), 5) oPCSFilter = BaseFilters.PhysicalCardSetFilter('Test Set 4') oGunFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.SpecificCardFilter('AK-47')]) aCSCards = [ IAbstractCard(x).name for x in oGunFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual(aCSCards, [u'AK-47', u'AK-47']) oVampireFilter = BaseFilters.FilterAndBox( [oPCSFilter, BaseFilters.CardTypeFilter('Vampire')]) aCSCards = [ IAbstractCard(x).name for x in oVampireFilter.select( MapPhysicalCardToPhysicalCardSet).distinct() ] self.assertEqual( aCSCards, [u'Abebe (Group 4)', u'Abebe (Group 4)', u'Abebe (Group 4)']) aPrintings = [oCard.printing for oCard in oCS.cards] aPrintings.sort(key=lambda x: x.id if x else -1) self.assertEqual(aPrintings, aExpectedPrintings)
def get_card(self, oPath): """Return the AbstractCard for the given path""" oIter = self.get_iter(oPath) sName = self.get_value(oIter, 0) return IAbstractCard(sName)
def test_basic(self): """Test behaviour""" oCard = IAbstractCard("Pier 13, Port of Baltimore") self.assertEqual(oCard, IAbstractCard("Pier 13")) oCard = IAbstractCard("Anastasz di Zagreb") self.assertEqual(oCard, IAbstractCard("Anastaszdi Zagreb")) oCard = IAbstractCard("The Path of Blood") # Article shifting self.assertEqual(oCard, IAbstractCard("Path of Blood, The")) # Odd cases self.assertEqual(oCard, IAbstractCard("THE PATH OF bLOOD")) self.assertEqual(oCard, IAbstractCard("the paTH oF bLOOD")) # Check that the AKA parsing works as expected oCard = IAbstractCard(u"L\xe1z\xe1r Dobrescu") self.assertEqual(oCard, IAbstractCard("Lazar Dobrescu")) # check (Adv) automatic lookups oCard = IAbstractCard(u"Kemintiri (Advanced)") self.assertEqual(oCard, IAbstractCard("Kemintiri (Adv)")) oCard = IAbstractCard(u"Alan Sovereign (Advanced)") self.assertEqual(oCard, IAbstractCard("Alan Sovereign (Adv)"))