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, num, show=None, author=None, makeDirs=False, dummy=False): self.table = Sequence.TABLE self.num = num self.show = show if show else env.getEnvironment('show') self._exists = None if dummy: return if num is None: raise ValueError('Sequence\'s num can\'t be None') try: self.num = int(num) except ValueError: raise ValueError( 'Sequence number must be a number, not: {}'.format(num)) 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.author = author if author else creationInfo[0] self.creation = creationInfo[1] s = Show.fromPk(self.show) if not s: raise ValueError('No such show: {}'.format(show)) else: self.work_path = os.path.join(s.work_path, self.directory) self.release_path = os.path.join(s.release_path, self.directory) p = Person(self.author) if not p.exists(): raise ValueError('No such user: {}'.format(self.author)) if makeDirs: if not os.path.isdir(self.work_path): os.makedirs(self.work_path) if not os.path.isdir(self.release_path): os.makedirs(self.release_path)
def fixerChanged(self): # Updates department combo box to reflect the "assigned user's" department username = str(self.LNE_assignTo.text()) deptIndex = self.CMB_dept.findText('general') if username and len(username) <= 10: user = Person(username) if user.exists(): deptIndex = self.CMB_dept.findText(user.department) if not self.fix: # Only do this convenience switching if we are making a new fix, otherwise it's really annoying self.CMB_dept.setCurrentIndex(deptIndex)
def handleRemoveUser(self): for selected in self.LST_users.selectedItems(): user = Person.fromPk(str(selected.text())) if not user: continue user.set('perm_group', PermissionGroup.DEFAULT)
def getUsers(): from helix.database.person import Person with Manager(willCommit=False) as mgr: query = """SELECT * FROM {}""".format(Person.TABLE) rows = mgr.connection().execute(query).fetchall() users = [] for r in rows: users.append(Person.dummy().unmap(r)) return users
def testPerson(self): person = Person('spaouellet') self.assertTrue(person._exists) self.assertTrue(person.exists()) self.assertEqual(person.full_name, None) self.assertEqual(person.department, None) self.assertIn(person.table, Manager.TABLE_LIST) self.assertTrue(person.exists()) # Random person self.assertFalse(Person('bob').exists()) person.set('full_name', 'Sasha Ouellet') del person person = Person('spaouellet') self.assertEqual(person.full_name, 'Sasha Ouellet') with Manager(willCommit=False) as mgr: for c in [c[0] for c in mgr.getColumnNames(person.table)]: self.assertTrue(hasattr(person, c)) # Try inserting again, should fail self.assertFalse(person.insert())
def handleAddUser(self): dialog = QDialog(self) layout = QVBoxLayout() user = QLineEdit(dialog) buttonLayout = QHBoxLayout() cancel = QPushButton('Cancel') create = QPushButton('Add') completer = QCompleter([p.username for p in hxdb.getUsers()], user) cancel.clicked.connect(dialog.reject) create.clicked.connect(dialog.accept) create.setDefault(True) user.setCompleter(completer) layout.addWidget(user) buttonLayout.addWidget(cancel) buttonLayout.addWidget(create) buttonLayout.insertStretch(0) layout.addLayout(buttonLayout) dialog.setWindowTitle('Add User') dialog.setLayout(layout) if dialog.exec_() == QDialog.Accepted: name = str(user.text()).strip() if name: user = Person.fromPk(name) if not user: raise ValueError('User: {} does not exist'.format(user)) group = str(self.LST_groups.selectedItems()[0].text()) user.set('perm_group', group) self.LST_users.addItem(name) self.LST_users.clearSelection() self.LST_users.setCurrentRow(self.LST_users.count() - 1)
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 __init__(self, shot, sequence, show=None, clipName=None, author=None, comment=None, start=None, end=None, makeDirs=False, dummy=False): self.table = Snapshot.TABLE self.show = show if show else env.getEnvironment('show') self.sequence = sequence self.shot = shot self._exists = None self.sequenceId = None self.shotId = None self.first_frame = start self.last_frame = end if dummy: return if not self.show: raise ValueError('Tried to fallback to environment-set show, but it was null.') s = Show.fromPk(self.show) if not s: raise ValueError('No such show: {}'.format(show)) 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('Shot 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.sequence, sh.show)) else: self.shotId = sh.id self.first_frame = self.first_frame if self.first_frame else sh.start self.last_frame = self.last_frame if self.last_frame else sh.end self.num = Snapshot.nextSnapshotNum(self.show, self.sequenceId, self.shotId) fetched = self.exists(fetch=True) if fetched: self.unmap(fetched) self._exists = True else: creationInfo = env.getCreationInfo(format=False) self.comment = comment self.author = author if author else creationInfo[0] self.creation = creationInfo[1] self.first_frame = start self.last_frame = end p = Person(self.author) if not p.exists(): raise ValueError('No such user: {}'.format(self.author)) shotDir = Shot.fromPk(self.shotId).release_path self.file_path = os.path.join(shotDir, '.snapshots', str(self.num)) if makeDirs and not os.path.isdir(self.file_path): os.makedirs(self.file_path)
def accept(self): show = str(self.CMB_show.currentText()) seq = int(str(self.CMB_seq.currentText())) if str(self.CMB_seq.currentText()) and str(self.CMB_seq.currentText()) != '--' else None shotIndex = self.CMB_shot.currentIndex() if str(self.CMB_shot.currentText()) and str(self.CMB_shot.currentText()) != '--' else None shot = self.shots[shotIndex] if shotIndex and self.shots else None elementIndex = self.CMB_asset.currentIndex() if str(self.CMB_asset.currentText()) and str(self.CMB_asset.currentText()) != '--' else None element = self.elements[elementIndex] if elementIndex and self.elements else None username = str(self.LNE_assignTo.text()) fixer = None status = str(self.CMB_status.currentText()) priority = int(self.CMB_priority.currentIndex()) dept = str(self.CMB_dept.currentText()) fixType = str(self.CMB_type.currentText()) if username and len(username) <= 10: fixer = Person(username) deadline = self.DATE_due.date().toPyDate() if self.CHK_due.isChecked() else None if self.fix: # Just update instead of making a new fix if fixType != self.fix.type: self.fix.set('type', fixType) if dept != self.fix.for_dept: self.fix.set('for_dept', dept) if status != self.fix.status: self.fix.set('status', status) if status == 'done': self.fix.set('fix_date', env.getCreationInfo(format=False)[1]) else: self.fix.set('fix_date', None) fixUser = fixer.username if fixer is not None else None if fixUser != self.fix.fixer: self.fix.set('fixer', fixUser) if fixer is not None: self.fix.set('assign_date', env.getCreationInfo(format=False)[1]) self.fix.set('status', 'assigned') else: self.fix.set('assign_date', None) self.fix.set('status', 'new') if priority != self.fix.priority: self.fix.set('priority', priority) if deadline != self.fix.deadline: self.fix.set('deadline', deadline) # Submit comment if text in box comment = str(self.TXT_addComment.toPlainText()) if comment and self.commentHasEntered: self.fix.addComment(comment) QMessageBox.information(self, 'Fix #{}'.format(self.fix.num), 'Changes submitted') else: # There's no command-line api for this because of how cumbersome it would be to type all these parameters from that interface fix = Fix( fixType, str(self.LNE_title.text()), str(self.TXT_body.toPlainText()), dept, show=show, sequence=seq, shot=shot.num if shot else None, clipName=shot.clipName if shot else None, elementName=element.name if element and not element.name.startswith('_') else None, elementType=element.type if element else None, status=status, priority=priority ) if fixer is not None and fixer.exists(): fix.fixer = fixer.username fix.assign_date = fix.creation fix.status = 'assigned' if deadline: fix.deadline = deadline if fix.insert(): QMessageBox.information(self, 'Submitted fix #{}'.format(fix.num), 'Successfully submitted fix!') super(FixDialog, self).accept()
def __init__(self, alias, resolution, fps, name=None, author=None, makeDirs=False, dummy=False): """Construct a new show. Based on the given parameter values, this may equate to a show that already exists in the DB, or will construct an entirely new instance. Args: alias (str): The alias (internal name) of the show resolution (tuple): The image resolution for the show fps (float): The frames per second that the show will follow name (str, optional): The long, descriptive name author (str, optional): The creator of the show, defaults to the current user makeDirs (bool, optional): Whether to make the show's directories on disk, if they don't already exist. dummy (bool, optional): Whether this is a throwaway instance or not. Dummy instances are meant to be "unmapped" into since they will have no attributes set. Raises: ValueError: If the alias specified does not meet the sanitation criteria, or if the given user (if any provided) does not exist in the database already. """ self.table = Show.TABLE if dummy: return sanitary, reasons = utils.isSanitary(alias) if not sanitary: raise ValueError('Invalid alias specified:' + '\n'.join(reasons)) self.alias = alias self._exists = None fetched = self.exists(fetch=True) if fetched: self.unmap(fetched) self._exists = True else: self._exists = False if not isinstance(resolution, tuple) or len(resolution) != 2: raise ValueError( 'Invalid resolution specified, must be a length 2 tuple representing the width and height values' ) self.resolution_x = resolution[0] self.resolution_y = resolution[1] self.fps = fps self.name = name creationInfo = env.getCreationInfo(format=False) self.author = author if author else creationInfo[0] self.creation = creationInfo[1] self.work_path = os.path.join(env.getEnvironment('work'), self.directory) self.release_path = os.path.join(env.getEnvironment('release'), self.directory) p = Person(self.author) if not p.exists(): raise ValueError('No such user: {}'.format(self.author)) if makeDirs: if not os.path.isdir(self.work_path): os.makedirs(self.work_path) if not os.path.isdir(self.release_path): os.makedirs(self.release_path)
def __init__(self, name, elType, show=None, sequence=None, shot=None, clipName=None, author=None, makeDirs=False, dummy=False): self.table = Element.TABLE if dummy: return if name is not None: sanitary, reasons = utils.isSanitary(name, maxChars=25) if not sanitary: raise ValueError('Invalid element name specified:' + '\n'.join(reasons)) self.name = name self.type = elType.lower() self.show = show if show else env.getEnvironment('show') self.sequence = sequence self.shot = shot self._exists = None self.sequenceId = None self.shotId = None if name is None: if shot is None or sequence is None: raise ValueError( 'Element\'s name can only be None (considered nameless) if shot and sequence are also specified' ) else: self.name = '_{}{}{}'.format( fileutils.SEQUENCE_FORMAT.format( str(self.sequence).zfill(env.SEQUENCE_SHOT_PADDING)), fileutils.SHOT_FORMAT.format( str(self.shot).zfill(env.SEQUENCE_SHOT_PADDING)), clipName if clipName else '') if not self.type: raise ValueError('Element\'s type can\'t be None') if self.type not in Element.ELEMENT_TYPES: raise ValueError( 'Invalid element type: {}. Must be one of: {}'.format( self.type, ', '.join(Element.ELEMENT_TYPES))) 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.author = author if author else creationInfo[0] self.creation = creationInfo[1] self.status = Element.STATUS[0] self.assigned_to = None self.pubVersion = 0 self.version = 1 self.thumbnail = None self.shot_clipName = clipName 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)) baseWorkDir = s.work_path baseReleaseDir = s.release_path 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 baseWorkDir = sq.work_path baseReleaseDir = sq.release_path if self.shot is not None and self.sequence is not None: try: self.shot = int(shot) except ValueError: raise ValueError( 'Shot number must be a number, not: {}'.format(shot)) sh = Shot(self.shot, self.sequence, show=self.show, clipName=self.shot_clipName) if not sh.exists(): raise ValueError( 'No such shot {} in sequence {} in show {}'.format( sh.num, sh.sequence, sh.show)) else: self.shotId = sh.id baseWorkDir = sh.work_path baseReleaseDir = sh.release_path self.work_path = os.path.join(baseWorkDir, self.directory) self.release_path = os.path.join(baseReleaseDir, self.directory) if makeDirs: if not os.path.isdir(self.work_path): os.makedirs(self.work_path) if not os.path.isdir(self.release_path): os.makedirs(self.release_path)
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