def testPF(self): el = Element('test', 'prop', 'foobar') pf = PublishedFile(el.name, el.type, '', show=el.show) self.assertFalse(pf.exists()) self.assertIsNotNone(pf.elementId) self.assertEqual(pf.version, 1) self.assertTrue(pf.insert()) # Nonextant element with self.assertRaises(ValueError): p = PublishedFile('nonextant', 'prop', '', show=el.show) # Nonextant fix with self.assertRaises(ValueError): e = Element('test2', 'prop', 'foobar') e.insert() p = PublishedFile(e.name, e.type, '', show=e.show, fix=2) self.assertEqual( PublishedFile(el.name, el.type, '', show=el.show).version, 2) with Manager(willCommit=False) as mgr: for c in [c[0] for c in mgr.getColumnNames(pf.table)]: self.assertTrue(hasattr(pf, c)) # Insert again.. self.assertFalse(pf.insert())
def getElement(self, name, elType): from helix.database.element import Element try: el = Element(name, elType, show=self.show, sequence=self.sequence, shot=self.shot) if el.exists(): return el else: return None except: return None
def target(self): if self.elementId: return Element.fromPk(self.elementId) elif self.shotId: return Shot.fromPk(self.shotId) elif self.sequenceId: return Sequence.fromPk(self.sequenceId) elif self.show: return Show.fromPk(self.show)
def getElements(): from helix.database.element import Element with Manager(willCommit=False) as mgr: query = """SELECT * FROM {}""".format(Element.TABLE) rows = mgr.connection().execute(query).fetchall() elements = [] for r in rows: elements.append(Element.dummy().unmap(r)) return elements
def setUpClass(cls): if not os.path.exists(os.environ['HELIX_DB']): if not os.path.isdir(os.path.dirname(os.environ['HELIX_DB'])): os.makedirs(os.path.dirname(os.environ['HELIX_DB'])) open(os.environ['HELIX_DB'], 'w').close() with Manager() as mgr: mgr.initTables() Person('spaouellet').insert() Person('foo').insert() Show('foobar', makeDirs=True).insert() Sequence(100, 'foobar', makeDirs=True).insert() Sequence(900, 'foobar', makeDirs=True).insert() Shot(100, 100, 'foobar', makeDirs=True).insert() Shot(200, 100, 'foobar', makeDirs=True).insert() Shot(200, 900, 'foobar', makeDirs=True).insert() Element('test', 'prop', 'foobar', makeDirs=True).insert() e = Element('camera', 'camera', 'foobar', sequence=100, makeDirs=True) e.set('assigned_to', 'foo', insertIfMissing=True) Element('render', 'plate', 'foobar', shot=100, sequence=100, makeDirs=True).insert() Fix('Test fix', 'This is the body', show='foobar').insert() env.setEnvironment('show', 'foobar')
def __init__(self, elementName, elementType, filePath, versionlessFilePath, show=None, sequence=None, shot=None, comment=None, fix=None, dummy=False): self.table = PublishedFile.TABLE if dummy: return self.elementName = elementName self.elementType = elementType self.show = show if show else env.getEnvironment('show') self.elementId = None self.fixId = None self._exists = None if not self.show: raise ValueError( 'Tried to fallback to environment-set show, but it was null.') if filePath is None: raise ValueError('Must provide a file path') if versionlessFilePath is None: raise ValueError('Must provide a versionless file path') if self.elementType is None: raise ValueError( 'Must provide an element type to attach this Published File to' ) e = Element(self.elementName, self.elementType, show=self.show, sequence=sequence, shot=shot) if not e.exists(): raise ValueError( 'No such element to attach to: {} ({}) in {}{}{}'.format( e.name, e.type, e.show, ' in sequence {}'.format(e.sequence), ' in shot {}'.format(e.shot))) else: self.elementId = e.id self.version = PublishedFile.nextVersion(self.show, self.elementId) fetched = self.exists(fetch=True) if fetched: self.unmap(fetched) self._exists = True else: self._exists = False creationInfo = env.getCreationInfo(format=False) self.author = creationInfo[0] self.creation = creationInfo[1] self.comment = comment self.file_path = filePath self.versionless_path = versionlessFilePath s = Show.fromPk(self.show) p = Person(self.author) if not s: raise ValueError('No such show: {}'.format(self.show)) if not p.exists(): raise ValueError('No such user: {}'.format(self.author)) if fix: f = Fix.byNum(fix, self.show) if not f or not f.exists(): raise ValueError( 'No such fix number: {} in show {}'.format( fix, self.show)) else: self.fixId = f.id
def testElement(self): el = Element('test', 'prop', 'foobar', 100, 100) self.assertFalse(el._exists) self.assertFalse(el.exists()) self.assertTrue(Show(el.show).exists()) self.assertTrue(Sequence(el.sequence, el.show).exists()) self.assertTrue(Shot(el.shot, el.sequence, el.show).exists()) self.assertTrue(Element('test', 'prop', 'foobar').exists()) el.insert() pf = PublishedFile('test', 'prop', '', shot=100, sequence=100, show='foobar') pf.insert() self.assertEqual(el.getPublishedFiles()[0].id, pf.id) self.assertIn(el.table, Manager.TABLE_LIST) self.assertFalse(os.path.exists(el.work_path)) self.assertFalse(os.path.exists(el.release_path)) # No element type with self.assertRaises(ValueError): badEl = Element('foo', None, 'foobar') # Can be nameless, but only if we give shot and seq with self.assertRaises(ValueError): badEl = Element(None, 'prop', 'foobar') # Should be procedurally generated self.assertIsNotNone(Element(None, 'prop', 'foobar', 100, 100).name) # Improper element type with self.assertRaises(ValueError): badEl = Element('foo', 'bar', 'foobar') with Manager(willCommit=False) as mgr: for c in [c[0] for c in mgr.getColumnNames(el.table)]: self.assertTrue(hasattr(el, c)) # Try inserting again, should fail self.assertFalse(Element('test', 'prop', 'foobar').insert())
def testShow(self): # TODO: validate table columns are in object attrs show = Show('foobar') self.assertTrue(show._exists) self.assertTrue(show.exists()) self.assertEqual( show.exists(fetch=True), ('foobar', None, '/tmp/helixTest/work/foobar', '/tmp/helixTest/release/foobar', 'spaouellet', show.creation)) self.assertEqual(show.alias, 'foobar') self.assertEqual(show.name, None) self.assertEqual(show.work_path, '/tmp/helixTest/work/foobar') self.assertEqual(show.release_path, '/tmp/helixTest/release/foobar') self.assertEqual(show.author, 'spaouellet') self.assertEqual(show, Show.fromPk(getattr(show, show.pk))) self.assertEqual(show.get('alias'), 'foobar') self.assertEqual( Sequence(100, 'foobar').id, show.getSequences([100])[0].id) self.assertEqual(len(show.getSequences(200)), 0) self.assertEqual( Shot(200, 900, 'foobar').id, show.getShots(900, 200)[0].id) self.assertEqual( Shot(200, 900, 'foobar').id, show.getShots(900, [100, 200])[0].id) self.assertEqual(len(show.getShots()), 3) self.assertEqual(len(show.getElements()), 3) self.assertEqual( Element('test', 'prop', 'foobar').id, show.getElements('test', 'prop')[0].id) self.assertEqual(len(show.getElements(status='ip')), 0) self.assertEqual(len(show.getElements(authors='bob')), 0) self.assertEqual(len(show.getElements(authors='spaouellet')), 3) self.assertEqual(len(show.getElements(assignedTo='foo')), 1) self.assertEqual( len(show.getElements(assignedTo='foo', authors='bob')), 0) with self.assertRaises(ValueError): # Non-sanitary alias Show('foo bar') with self.assertRaises(ValueError): # Long alias Show('thisaliasiswaytoolong') # Nonextant attributes self.assertIs(show.get('randomAttr'), None) self.assertEqual(show.get('randomAttr', 'default'), 'default') self.assertIn(show.table, Manager.TABLE_LIST) self.assertTrue(os.path.exists(show.work_path)) self.assertTrue(os.path.exists(show.release_path)) # Test dummy show doesn't exist nonextant = Show('nonextant') self.assertFalse(nonextant._exists) self.assertFalse(nonextant.exists()) self.assertIs(nonextant.exists(fetch=True), None) show.set('name', 'Testing') del show show = Show('foobar') # Remaking, should have saved show.name self.assertEqual(show.name, 'Testing') # Test setting on a non-db-extant show show2 = Show('show2') show2.set('name', 'Show2') # We set without inserting del show2 show2 = Show('show2') self.assertIs(show2.name, None) # Now set while inserting show2.set('name', 'Show2', insertIfMissing=True) del show2 show2 = Show('show2') self.assertEqual(show2.name, 'Show2') # Table columns exist in attrs with Manager(willCommit=False) as mgr: for c in [c[0] for c in mgr.getColumnNames(show2.table)]: self.assertTrue(hasattr(show2, c)) # Try inserting again, should fail self.assertFalse(show.insert())
def initUI(self): self.CMB_type.addItems(Fix.TYPES) self.CMB_status.setDisabled(self.fix is None) self.CMB_status.addItems(Fix.STATUS.values()) self.CMB_priority.addItems(['{}{}'.format(k, ' (' + v + ')' if v else '') for k, v in Fix.PRIORITY.iteritems()]) self.CMB_priority.setCurrentIndex(3) self.CMB_dept.addItems(['general'] + env.cfg.departments) completionList = [u.username for u in db.getUsers()] self.assignedCompleter = QCompleter(completionList, self.LNE_assignTo) self.assignedCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.assignedCompleter.setCompletionMode(QCompleter.InlineCompletion) self.LNE_assignTo.setCompleter(self.assignedCompleter) self.LNE_assignTo.textChanged.connect(self.fixerChanged) self.CMB_show.addItems([s.alias for s in db.getShows()]) self.CMB_show.setCurrentIndex(self.CMB_show.findText(env.getEnvironment('show'))) today = QDate.currentDate() self.DATE_due.setDate(today.addDays(14)) self.CHK_due.clicked.connect(self.toggleDue) self.toggleDue() self.populateSeqAndShot() if self.fix is not None: self.CMB_status.setCurrentIndex(self.CMB_status.findText(self.fix.status)) self.CMB_priority.setCurrentIndex(self.fix.priority) self.CMB_dept.setCurrentIndex(self.CMB_dept.findText(self.fix.for_dept if self.fix.for_dept else 'general')) self.LNE_assignTo.setText(self.fix.fixer if self.fix.fixer else '') self.CMB_show.setCurrentIndex(self.CMB_show.findText(self.fix.show)) self.CMB_show.setDisabled(True) self.populateSeqAndShot() if self.fix.sequence: self.CMB_seq.setCurrentIndex(self.CMB_seq.findText(str(self.fix.sequence))) self.CMB_seq.setDisabled(True) self.populateShots() if self.fix.shot: shot = Shot.fromPk(self.fix.shotId) for i, s in enumerate(self.shots): if s == shot: self.CMB_shot.setCurrentIndex(i) break self.CMB_shot.setDisabled(True) self.populateElements() if self.fix.elementId: el = Element.fromPk(self.fix.elementId) for i, e in enumerate(self.elements): if e == el: self.CMB_asset.setCurrentIndex(i) break self.CMB_asset.setDisabled(True) if self.fix.deadline: dt = utils.dbTimetoDt(self.fix.deadline) self.DATE_due.setDate(QDate(dt.year, dt.month, dt.day)) self.CHK_due.setCheckState(Qt.Checked) self.LNE_title.setText(self.fix.title) self.TXT_body.setPlainText(self.fix.body) self.LNE_title.setReadOnly(True) self.TXT_body.setReadOnly(True) for comment in reversed(self.fix.commentList): commentWidget = CommentWidget(self, comment) self.LAY_comments.addWidget(commentWidget) commentWidget.replied.connect(self.handleCommentReply) self.setWindowTitle('Fix #{} ({})'.format(self.fix.num, self.fix.show)) else: self.GRP_activity.setVisible(False) self.TXT_addComment.setVisible(False) self.resize(self.width(), 200)
def __init__(self, fixType, title, body, dept, show=None, sequence=None, shot=None, clipName=None, elementName=None, elementType=None, author=None, status=STATUS[0], priority=3, dummy=False): self.table = Fix.TABLE self.commentList = [] if dummy: return self.title = title self.body = body self.show = show if show else env.getEnvironment('show') self.sequence = sequence self.shot = shot self.elementName = elementName self.elementType = elementType self._exists = None self.sequenceId = None self.shotId = None self.elementId = None if not title: raise ValueError('Must specify a fix title') if not body: raise ValueError( 'Must specify details for the fix in the body text') if not self.show: raise ValueError( 'Tried to fallback to environment-set show, but it was null.') fetched = self.exists(fetch=True) if fetched: self.unmap(fetched) self._exists = True else: creationInfo = env.getCreationInfo(format=False) self.type = fixType.lower() self.author = author if author else creationInfo[0] self.creation = creationInfo[1] self.status = status if status in Fix.STATUS.values( ) else Fix.STATUS[0] self.priority = priority if priority in Fix.PRIORITY.keys() else 3 self.fixer = None self.fix_date = None self.deadline = None self.assign_date = None self.num = Fix.nextFixNum(self.show) self.for_dept = dept.lower() if self.type not in Fix.TYPES: raise ValueError('Type must be one of: {}, not: {}'.format( ', '.join(Fix.TYPES, self.type))) if self.for_dept not in env.cfg.departments and self.for_dept != 'general': raise ValueError( 'Invalid department ({}) to assign fix to. Options are: {}' .format(self.for_dept, ', '.join(['general'] + env.cfg.departments))) s = Show.fromPk(self.show) if not s: raise ValueError('No such show: {}'.format(show)) p = Person(self.author) if not p.exists(): raise ValueError('No such user: {}'.format(self.author)) if self.sequence is not None: try: self.sequence = int(self.sequence) except ValueError: raise ValueError( 'Sequence number must be a number, not: {}'.format( self.sequence)) sq = Sequence(self.sequence, show=self.show) if not sq.exists(): raise ValueError('No such sequence {} in show {}'.format( sq.num, sq.show)) else: self.sequenceId = sq.id if self.shot is not None and self.sequence is not None: try: self.shot = int(shot) except ValueError: raise ValueError( 'Sequence number must be a number, not: {}'.format( shot)) sh = Shot(self.shot, self.sequence, show=self.show, clipName=clipName) if not sh.exists(): raise ValueError( 'No such shot {}{} in sequence {} in show {}'.format( sh.num, sh.clipName if sh.clipName else '', sh.sequence, sh.show)) else: self.shotId = sh.id if self.elementType: el = Element(self.elementName, self.elementType, self.show, self.sequence, self.shot) if not el.exists(): raise ValueError( 'No such element {} ({}){}{} in show {}'.format( el.name, el.type, ' in shot {}'.format(el.shot) if el.shot else '', ' in sequence {}'.format(el.sequence) if el.sequence else '', el.show)) else: self.elementId = el.id
def getElements(self, names=[], types=[], shows=[], seqs=[], shots=[], clips=[], authors=[], assignedTo=[], status=[], debug=False): from helix.database.sql import Manager from helix.database.element import Element with Manager(willCommit=False) as mgr: query = """SELECT * FROM {}""".format(Element.TABLE) statement = 'WHERE' if names is not None: if isinstance(names, basestring): names = [names] if names: query += " {} name IN ({})".format( statement, ','.join(["'{}'".format(n) for n in names])) statement = 'AND' if types is not None: if isinstance(types, basestring): types = [types] if types: query += " {} type IN ({})".format( statement, ','.join(["'{}'".format(n) for n in types])) statement = 'AND' if shows is not None: if isinstance(shows, basestring): shows = [shows] if shows: query += " {} show IN ({})".format( statement, ','.join(["'{}'".format(n) for n in shows])) statement = 'AND' if seqs is not None: if isinstance(seqs, int): seqs = [seqs] if seqs: if isinstance(seqs, basestring) and seqs.lower() == 'null': query += " {} sequence IS NULL".format(statement) else: query += " {} sequence IN ({})".format( statement, ','.join(["'{}'".format(n) for n in seqs])) statement = 'AND' if shots is not None: if isinstance(shots, int): shots = [shots] if shots: if isinstance(shots, basestring) and shots.lower() == 'null': query += " {} shot IS NULL".format(statement) else: query += " {} shot IN ({})".format( statement, ','.join(["'{}'".format(n) for n in shots])) statement = 'AND' if clips is not None: if isinstance(clips, basestring): clips = [clips] if clips: if clips[0].lower() != 'null': query += " {} shot_clipName IN ({})".format( statement, ','.join(["'{}'".format(n) for n in clips])) else: query += " {} shot_clipName IS NULL".format(statement) statement = 'AND' if status is not None: if isinstance(status, basestring): status = [status] if status: if status[0].lower() != 'null': query += " {} status IN ({})".format( statement, ','.join(["'{}'".format(n) for n in status])) else: query += " {} status IS NULL".format(statement) statement = 'AND' if authors is not None: if isinstance(authors, basestring): authors = [authors] if authors: if authors[0].lower() != 'null': query += " {} author IN ({})".format( statement, ','.join(["'{}'".format(n) for n in authors])) else: query += " {} author IS NULL".format(statement) statement = 'AND' if assignedTo is not None: if isinstance(assignedTo, basestring): assignedTo = [assignedTo] if assignedTo: if assignedTo[0].lower() != 'null': query += " {} assigned_to IN ({})".format( statement, ','.join(["'{}'".format(n) for n in assignedTo])) else: query += " {} assigned_to IS NULL".format(statement) statement = 'AND' elements = [] if debug: print 'QUERY:', query for row in mgr.connection().execute(query).fetchall(): elements.append(Element.dummy().unmap(row)) return elements