def test_authenticate_updates_user_password_if_stalker_fails_but_ldap_successes(ldap_server, create_db, monkeypatch): """testing if the anima.utils.authenticate() will update the user password if stalker fails but ldap doesn't fail and the user exists """ from ldap3.extend import StandardExtendedOperations def mock_return(*arg, **kwargs): return "pipeline" monkeypatch.setattr(StandardExtendedOperations, "who_am_i", mock_return) # This is not working with mock server login = '******' ldap_password = '******' stalker_password = '******' # create a user in Stalker with a different password from stalker import User from stalker.db.session import DBSession new_user = User(login=login, password=stalker_password, email='*****@*****.**', name='Pipeline') DBSession.add(new_user) DBSession.commit() assert new_user.check_password(ldap_password) is False assert new_user.check_password(stalker_password) is True # now authenticate with the new password from anima.utils import authenticate result = authenticate(login, ldap_password) # result should be True assert result is True # and the password should be updated pipeline_user = User.query.filter(User.login==login).first() assert pipeline_user is not None assert new_user.check_password(ldap_password) is True assert new_user.check_password(stalker_password) is False
def test_status_list_attribute_is_skipped_and_there_is_a_db_setup_but_no_suitable_StatusList( self): """testing if a TypeError will be raised even a database is setup but there is no suitable StatusList for StatusListNoAutoAddClass in the database """ # create a StatusList for StatusListAutoAddClass test_status_list = StatusList( name="StatusListAutoAddClass Statuses", statuses=[ Status(name="Status1", code="Sts1"), Status(name="Status2", code="Sts2"), Status(name="Status3", code="Sts3"), ], target_entity_type=StatusListAutoAddClass, ) # add it to the db from stalker.db.session import DBSession DBSession.add(test_status_list) DBSession.commit() # now try to create a StatusListAutoAddClass without a status_list # argument with pytest.raises(TypeError) as cm: StatusListNoAutoAddClass(name="Test StatusListNoAutoAddClass") assert str(cm.value) == \ "StatusListNoAutoAddClass instances can not be initialized " \ "without a stalker.models.status.StatusList instance, please " \ "pass a suitable StatusList " \ "(StatusList.target_entity_type=StatusListNoAutoAddClass) with " \ "the 'status_list' argument"
def test_status_list_attribute_is_skipped_and_there_is_a_db_setup(self): """testing if there will be no error and the status_list attribute is filled with the correct StatusList instance coming from the database if there is already a database setup and there is a StatusList instance defined for the StatusListAutoAddClass. """ # create a StatusList for StatusListAutoAddClass test_status_list = StatusList( name="StatusListAutoAddClass Statuses", statuses=[ Status(name="Status1", code="Sts1"), Status(name="Status2", code="Sts2"), Status(name="Status3", code="Sts3"), ], target_entity_type=StatusListAutoAddClass, ) # add it to the db DBSession.add(test_status_list) DBSession.commit() # now try to create a StatusListAutoAddClass without a status_list # argument test_StatusListAutoAddClass = StatusListAutoAddClass( name="Test StatusListAutoAddClass", ) # now check if the status_list is equal to test_status_list self.assertEqual( test_StatusListAutoAddClass.status_list, test_status_list )
def test_start_end_and_duration_values_are_rounded_to_the_Studio_timing_resolution( self): """testing if the start and end dates are rounded to the Studio timing_resolution """ import logging logging.getLogger('stalker.models.studio').setLevel(logging.DEBUG) from stalker.models.studio import Studio studio = Studio(name='Test Studio', timing_resolution=datetime.timedelta(minutes=5)) from stalker.db.session import DBSession DBSession.add(studio) DBSession.commit() self.kwargs['start'] = \ datetime.datetime(2013, 3, 22, 2, 38, 55, 531, tzinfo=pytz.utc) self.kwargs['end'] = \ datetime.datetime(2013, 3, 24, 16, 46, 32, 102, tzinfo=pytz.utc) new_foo_obj = DateRangeMixFooMixedInClass(**self.kwargs) # check the start expected_start = \ datetime.datetime(2013, 3, 22, 2, 40, tzinfo=pytz.utc) assert new_foo_obj.start == expected_start # check the end expected_end = \ datetime.datetime(2013, 3, 24, 16, 45, tzinfo=pytz.utc) assert new_foo_obj.end == expected_end # check the duration assert new_foo_obj.duration == expected_end - expected_start
def set_shot_from_range(self, version): """sets the Shot.cut_in and Shot.cut_out attributes from the current frame range if the current task is related to a Stalker Shot instance. :param Stalker.Version version: A Stalker Version instance. :return: """ # check if this is a shot related task is_shot_related_task = False shot = None from stalker import Shot for task in version.task.parents: if isinstance(task, Shot): is_shot_related_task = True shot = task break if is_shot_related_task and shot: # set frame ranges cut_in, cut_out = self.get_frame_range() shot.cut_in = int(cut_in) shot.cut_out = int(cut_out) from stalker.db.session import DBSession DBSession.add(shot) DBSession.commit()
def update_sequence(request): """runs when adding a new sequence """ logged_in_user = get_logged_in_user(request) sequence_id = request.params.get('sequence_id') sequence = Sequence.query.filter_by(id=sequence_id).first() name = request.params.get('name') code = request.params.get('code') status_id = request.params.get('status_id') status = Status.query.filter_by(id=status_id).first() if sequence and code and name and status: # get descriptions description = request.params.get('description') #update the sequence sequence.name = name sequence.code = code sequence.description = description sequence.status = status sequence.updated_by = logged_in_user sequence.date_updated = datetime.datetime.now() DBSession.add(sequence) else: logger.debug('there are missing parameters') logger.debug('name : %s' % name) logger.debug('status : %s' % status) HTTPServerError() return HTTPOk()
def accept(self): """overridden accept method """ if not self.name_lineEdit.is_valid: QtWidgets.QMessageBox.critical( self, 'Error', 'Please fix <b>name</b> field!' ) return name = self.name_lineEdit.text() windows_path = self.windows_path_lineEdit.text() linux_path = self.linux_path_lineEdit.text() osx_path = self.osx_path_lineEdit.text() from stalker import Repository from stalker.db.session import DBSession logged_in_user = self.get_logged_in_user() if self.mode == 'Create': # Create a new Repository try: repo = Repository( name=name, windows_path=windows_path, linux_path=linux_path, osx_path=osx_path ) self.repository = repo DBSession.add(repo) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical( self, 'Error', str(e) ) return elif self.mode == 'Update': # Update the repository try: self.repository.name = name self.repository.windows_path = windows_path self.repository.linux_path = linux_path self.repository.osx_path = osx_path self.repository.updated_by = logged_in_user DBSession.add(self.repository) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical( self, 'Error', str(e) ) return super(MainDialog, self).accept()
def setUp(self): """setup the test """ super(SequenceTester, self).setUp() # create a test project, user and a couple of shots from stalker import Type self.project_type = Type( name="Test Project Type", code='test', target_entity_type='Project', ) from stalker.db.session import DBSession DBSession.add(self.project_type) # create a repository self.repository_type = Type( name="Test Type", code='test', target_entity_type='Repository' ) DBSession.add(self.repository_type) from stalker import Repository self.test_repository = Repository( name="Test Repository", type=self.repository_type, ) DBSession.add(self.test_repository) # create projects from stalker import Project self.test_project = Project( name="Test Project 1", code='tp1', type=self.project_type, repository=self.test_repository, ) DBSession.add(self.test_project) self.test_project2 = Project( name="Test Project 2", code='tp2', type=self.project_type, repository=self.test_repository, ) DBSession.add(self.test_project2) # the parameters self.kwargs = { "name": "Test Sequence", 'code': 'tseq', "description": "A test sequence", "project": self.test_project, } # the test sequence from stalker import Sequence self.test_sequence = Sequence(**self.kwargs) DBSession.commit()
def loads(self, data): """Decodes Stalker data :param data: :return: """ from stalker.db.session import DBSession from stalker import Asset, Task, Shot, Sequence, Version, Type if isinstance(data, str): data = json.loads(data) # get the entity_type entity_type = data['entity_type'] # set default entity class to Task entity_class = Task if entity_type == 'Asset': entity_class = Asset elif entity_type == 'Shot': entity_class = Shot # this is a bug data['sequences'] = [] elif entity_type == 'Sequence': entity_class = Sequence version_data = data['versions'] data['versions'] = [] # get the type if 'type' in data: type_data = data['type'] if type_data: type_name = type_data['name'] type_ = Type.query.filter(Type.name == type_name).first() if not type_: # create a Type type_ = Type(**type_data) data['type'] = type_ data['project'] = self.project entity = entity_class(**data) DBSession.add(entity) DBSession.commit() # create Versions if version_data: for v_data in version_data: # get Version info v_data['task'] = entity v = Version(**v_data) # update version_number v.version_number = v_data['version_number'] v.is_published = v_data['is_published'] # for each child task call a new StalkerEntityDecoder for t in data['tasks']: child_task = self.loads(t) entity.tasks.append(child_task) return entity
def setUp(self): """setup the test """ super(RepositoryTester, self).setUp() self.patcher = PlatformPatcher() # create a couple of test tags from stalker import Tag self.test_tag1 = Tag(name="test tag 1") self.test_tag2 = Tag(name="test tag 2") self.kwargs = { "name": "a repository", "description": "this is for testing purposes", "tags": [self.test_tag1, self.test_tag2], "linux_path": "/mnt/M/Projects", "osx_path": "/Volumes/M/Projects", "windows_path": "M:/Projects" } from stalker import Repository from stalker.db.session import DBSession self.test_repo = Repository(**self.kwargs) DBSession.add(self.test_repo) DBSession.commit()
def test_version_number_attribute_is_set_to_a_lower_then_it_should_be(self): """testing if the version_number attribute will be set to a correct unique value when it is set to a lower number then it should be """ self.test_version.version_number = -1 self.assertEqual(self.test_version.version_number, 1) self.test_version.version_number = -10 self.assertEqual(self.test_version.version_number, 1) DBSession.add(self.test_version) DBSession.commit() self.test_version.version_number = -100 # it should be 1 again self.assertEqual(self.test_version.version_number, 1) new_version = Version(**self.kwargs) self.assertEqual(new_version.version_number, 2) new_version.version_number = 1 self.assertEqual(new_version.version_number, 2) new_version.version_number = 100 self.assertEqual(new_version.version_number, 100)
def test_update_paths_will_preserve_extension(self): """testing if update_paths method will preserve the extension. """ # create a FilenameTemplate for Task instances ft = FilenameTemplate( name="Task Filename Template", target_entity_type="Task", path="{{project.code}}/{%- for parent_task in parent_tasks -%}" "{{parent_task.nice_name}}/{%- endfor -%}", filename="{{task.nice_name}}_{{version.take_name}}" '_v{{"%03d"|format(version.version_number)}}{{extension}}', ) self.test_project.structure.templates.append(ft) new_version1 = Version(**self.kwargs) DBSession.add(new_version1) DBSession.commit() new_version1.update_paths() self.assertEqual(new_version1.path, "tp/SH001/Task1") extension = ".ma" new_version1.extension = extension self.assertEqual(new_version1.filename, "Task1_TestTake_v001.ma") # rename the task and update the paths self.test_task1.name = "Task2" # now call update_paths and expect the extension to be preserved new_version1.update_paths() self.assertEqual(new_version1.filename, "Task2_TestTake_v001.ma") self.assertEqual(new_version1.extension, extension)
def test_tasks_are_correctly_scheduled_when_compute_resources_is_False( self): """testing if the tasks are correctly scheduled when the compute resources is False """ tjp_sched = TaskJugglerScheduler(compute_resources=False) from stalker import Studio test_studio = Studio(name='Test Studio', now=datetime.datetime(2013, 4, 16, 0, 0, tzinfo=pytz.utc)) test_studio.start = \ datetime.datetime(2013, 4, 16, 0, 0, tzinfo=pytz.utc) test_studio.end = datetime.datetime(2013, 4, 30, 0, 0, tzinfo=pytz.utc) test_studio.daily_working_hours = 9 from stalker.db.session import DBSession DBSession.add(test_studio) tjp_sched.studio = test_studio tjp_sched.schedule() DBSession.commit() # check if the task and project timings are all adjusted assert \ datetime.datetime(2013, 4, 16, 9, 0, tzinfo=pytz.utc) == \ self.test_proj1.computed_start assert \ datetime.datetime(2013, 4, 24, 10, 0, tzinfo=pytz.utc) == \ self.test_proj1.computed_end assert \ datetime.datetime(2013, 4, 16, 9, 0, tzinfo=pytz.utc) == \ self.test_task1.computed_start assert \ datetime.datetime(2013, 4, 18, 16, 0, tzinfo=pytz.utc) == \ self.test_task1.computed_end assert len(self.test_task1.computed_resources) == 2 assert self.test_task1.computed_resources[0] in \ [self.test_user1, self.test_user2, self.test_user3, self.test_user4, self.test_user5] assert self.test_task1.computed_resources[1] in \ [self.test_user1, self.test_user2, self.test_user3, self.test_user4, self.test_user5] assert \ datetime.datetime(2013, 4, 18, 16, 0, tzinfo=pytz.utc) == \ self.test_task2.computed_start assert \ datetime.datetime(2013, 4, 24, 10, 0, tzinfo=pytz.utc) == \ self.test_task2.computed_end assert len(self.test_task2.computed_resources) == 2 assert self.test_task2.computed_resources[0] in \ [self.test_user1, self.test_user2, self.test_user3, self.test_user4, self.test_user5] assert self.test_task2.computed_resources[1] in \ [self.test_user1, self.test_user2, self.test_user3, self.test_user4, self.test_user5]
def test_OverbookedError_9(self): """testing if no OverBookedError will be raised when the resource is not already booked for the given time period. Simple case diagram: ####### ####### """ # time_log1 kwargs = copy.copy(self.kwargs) kwargs["resource"] = self.test_resource2 kwargs["start"] =\ datetime.datetime(2013, 3, 22, 4, 0, tzinfo=pytz.utc) \ + datetime.timedelta(20) kwargs["duration"] = datetime.timedelta(5) time_log1 = TimeLog(**kwargs) from stalker.db.session import DBSession DBSession.add(time_log1) DBSession.commit() # time_log2 kwargs["start"] = \ datetime.datetime(2013, 3, 22, 4, 0, tzinfo=pytz.utc) # no warning time_log2 = TimeLog(**kwargs) DBSession.add(time_log2) DBSession.commit()
def test_latest_version_attribute_is_working_properly(self): """testing if the last_version attribute is working properly """ new_version1 = Version(**self.kwargs) DBSession.add(new_version1) DBSession.commit() new_version2 = Version(**self.kwargs) DBSession.add(new_version2) DBSession.commit() new_version3 = Version(**self.kwargs) DBSession.add(new_version3) DBSession.commit() new_version4 = Version(**self.kwargs) DBSession.add(new_version4) DBSession.commit() new_version5 = Version(**self.kwargs) DBSession.add(new_version5) DBSession.commit() self.assertEqual(new_version5.version_number, 5) self.assertEqual(new_version1.latest_version, new_version5) self.assertEqual(new_version2.latest_version, new_version5) self.assertEqual(new_version3.latest_version, new_version5) self.assertEqual(new_version4.latest_version, new_version5) self.assertEqual(new_version5.latest_version, new_version5)
def upload_thumbnail(task, thumbnail_full_path): """Uploads the given thumbnail for the given entity :param task: An instance of :class:`~stalker.models.entity.SimpleEntity` or a derivative. :param str thumbnail_full_path: A string which is showing the path of the thumbnail image """ extension = os.path.splitext(thumbnail_full_path)[-1] # move the file to the task thumbnail folder # and mimic StalkerPyramids output format thumbnail_original_file_name = 'thumbnail%s' % extension thumbnail_final_full_path = os.path.join( task.absolute_path, 'Thumbnail', thumbnail_original_file_name ) try: os.makedirs(os.path.dirname(thumbnail_final_full_path)) except OSError: pass # # convert the thumbnail to jpg if it is a format that is not supported by # # browsers # ext_not_supported_by_browsers = ['.bmp', '.tga', '.tif', '.tiff', '.exr'] # if extension in ext_not_supported_by_browsers: # # use MediaManager to convert them # from anima.utils import MediaManager # mm = MediaManager() # thumbnail_full_path = mm.generate_image_thumbnail(thumbnail_full_path) shutil.copy(thumbnail_full_path, thumbnail_final_full_path) from stalker import Link, Version, Repository thumbnail_os_independent_path = \ Repository.to_os_independent_path(thumbnail_final_full_path) l_thumb = Link.query\ .filter(Link.full_path == thumbnail_os_independent_path).first() if not l_thumb: l_thumb = Link( full_path=thumbnail_os_independent_path, original_filename=thumbnail_original_file_name ) task.thumbnail = l_thumb # get a version of this Task from stalker.db.session import DBSession v = Version.query.filter(Version.task == task).first() if v: for naming_parent in v.naming_parents: if not naming_parent.thumbnail: naming_parent.thumbnail = l_thumb DBSession.add(naming_parent) DBSession.add(l_thumb) DBSession.commit()
def test_logged_in_user_returns_the_stored_User_instance_from_last_time( self): """testing if logged_in_user returns the logged in user """ # create a new user from stalker import User new_user = User(name='Test User', login='******', email='*****@*****.**', password='******') # save it to the Database from stalker.db.session import DBSession DBSession.add(new_user) DBSession.commit() assert new_user.id is not None # save it to the local storage from stalker import LocalSession local_session = LocalSession() local_session.store_user(new_user) # save the session local_session.save() # now get it back with a new local_session local_session2 = LocalSession() assert local_session2.logged_in_user_id == new_user.id assert local_session2.logged_in_user == new_user
def setUp(self): """set the test """ super(SimpleEntityDBTester, self).setUp() from stalker import User import json self.test_user = User( name="Test User", login="******", email="*****@*****.**", password="******", generic_text=json.dumps({'Phone number': '123'}, sort_keys=True), ) from stalker.db.session import DBSession DBSession.add(self.test_user) DBSession.commit() import datetime import pytz self.date_created = \ datetime.datetime(2010, 10, 21, 3, 8, 0, tzinfo=pytz.utc) self.date_updated = self.date_created self.kwargs = { "name": "Test Entity", "code": "TstEnt", "description": "This is a test entity, and this is a proper \ description for it", "created_by": self.test_user, "updated_by": self.test_user, "date_created": self.date_created, "date_updated": self.date_updated, 'generic_text': json.dumps({'Phone number': '123'}, sort_keys=True), }
def test_OverbookedError_3(self): """testing if a OverBookedError will be raised when the resource is already booked for the given time period. Simple case diagram: ##### ####### """ # time_log1 kwargs = copy.copy(self.kwargs) kwargs["resource"] = self.test_resource2 kwargs["start"] = datetime.datetime(2013, 3, 22, 4, 0, tzinfo=pytz.utc) kwargs["duration"] = datetime.timedelta(8) time_log1 = TimeLog(**kwargs) from stalker.db.session import DBSession DBSession.add(time_log1) DBSession.commit() # time_log2 kwargs["duration"] = datetime.timedelta(10) from stalker.exceptions import OverBookedError with pytest.raises(OverBookedError) as cm: TimeLog(**kwargs) assert str(cm.value) == \ 'The resource has another TimeLog between %s and %s' % ( time_log1.start, time_log1.end )
def test_status_list_attribute_is_skipped_and_there_is_a_db_setup_but_no_suitable_StatusList( self): """testing if a TypeError will be raised even a database is setup but there is no suitable StatusList for StatusListNoAutoAddClass in the database """ # create a StatusList for StatusListAutoAddClass test_status_list = StatusList( name="StatusListAutoAddClass Statuses", statuses=[ Status(name="Status1", code="Sts1"), Status(name="Status2", code="Sts2"), Status(name="Status3", code="Sts3"), ], target_entity_type=StatusListAutoAddClass, ) # add it to the db DBSession.add(test_status_list) DBSession.commit() # now try to create a StatusListAutoAddClass without a status_list # argument self.assertRaises( TypeError, StatusListNoAutoAddClass, **{"name": "Test StatusListNoAutoAddClass"} )
def test_is_latest_published_version_is_working_properly(self): """testing if the is_latest_published_version is working properly """ new_version1 = Version(**self.kwargs) DBSession.add(new_version1) DBSession.commit() new_version2 = Version(**self.kwargs) DBSession.add(new_version2) DBSession.commit() new_version3 = Version(**self.kwargs) DBSession.add(new_version3) DBSession.commit() new_version4 = Version(**self.kwargs) DBSession.add(new_version4) DBSession.commit() new_version5 = Version(**self.kwargs) DBSession.add(new_version5) DBSession.commit() new_version1.is_published = True new_version3.is_published = True new_version4.is_published = True self.assertFalse(new_version1.is_latest_published_version()) self.assertFalse(new_version2.is_latest_published_version()) self.assertFalse(new_version3.is_latest_published_version()) self.assertTrue(new_version4.is_latest_published_version()) self.assertFalse(new_version5.is_latest_published_version())
def test_stalker_entity_decoder_will_not_create_existing_tasks(create_db, create_empty_project): """testing if JSON decoder will not recreate existing data """ from stalker import Task project = create_empty_project import json from anima.utils import task_hierarchy_io global __here__ file_path = os.path.join(__here__, "data", "test_template3.json") with open(file_path) as f: data = json.load(f) decoder = \ task_hierarchy_io.StalkerEntityDecoder( project=project ) loaded_entity = decoder.loads(data) from stalker.db.session import DBSession DBSession.add(loaded_entity) DBSession.commit() # now there should be only one Assets task from stalker import Task assets_tasks = Task.query.filter(Task.name=='Assets').all() assert len(assets_tasks) == 1
def create_good(request): """creates a new Good """ logger.debug('***create good method starts ***') logged_in_user = get_logged_in_user(request) utc_now = local_to_utc(datetime.datetime.now()) came_from = request.params.get('came_from', '/') name = request.params.get('name', None) msrp = request.params.get('msrp', None) unit = request.params.get('unit', None) cost = request.params.get('cost', None) price_list_name = request.params.get('price_list_name', None) logger.debug('came_from : %s' % came_from) logger.debug('name : %s' % name) logger.debug('msrp : %s' % msrp) logger.debug('unit : %s' % unit) logger.debug('cost : %s' % cost) logger.debug('price_list_name : %s' % price_list_name) # create and add a new good if name and msrp and unit and cost and price_list_name: price_list = query_price_list(price_list_name) try: # create the new group new_good = Good(name=name, msrp=int(msrp), unit=unit, cost=int(cost), price_lists=[price_list]) new_good.created_by = logged_in_user new_good.date_created = utc_now new_good.date_updated = utc_now new_good.price_lists = [price_list] DBSession.add(new_good) logger.debug('added new good successfully') request.session.flash('success:Good <strong>%s</strong> is ' 'created successfully' % name) logger.debug('***create good method ends ***') except BaseException as e: request.session.flash('error: %s' % e) HTTPFound(location=came_from) else: logger.debug('not all parameters are in request.params') transaction.abort() return Response('There are missing parameters: ' 'name: %s' % name, 500) return Response('successfully created %s!' % name)
def setUp(self): """set up the test """ db.setup() db.init() self.temp_path = tempfile.mkdtemp() self.repo = Repository( name='Test Repository', linux_path=self.temp_path, windows_path=self.temp_path, osx_path=self.temp_path ) self.status_new = Status.query.filter_by(code='NEW').first() self.status_wip = Status.query.filter_by(code='WIP').first() self.status_cmpl = Status.query.filter_by(code='CMPL').first() self.project_status_list = \ StatusList.query.filter_by(target_entity_type='Project').first() self.task_filename_template = FilenameTemplate( name='Task Filename Template', target_entity_type='Task', path='{{project.code}}/{%- for parent_task in parent_tasks -%}' '{{parent_task.nice_name}}/{%- endfor -%}', filename='{{version.nice_name}}' '_v{{"%03d"|format(version.version_number)}}{{extension}}' ) self.project_structure = Structure( name='Project Structure', templates=[self.task_filename_template] ) self.project = Project( name='Test Project', code='TP', status_list=self.project_status_list, repository=self.repo, structure=self.project_structure ) self.task = Task( name='Test Task', project=self.project ) from stalker.db.session import DBSession DBSession.add(self.task) DBSession.commit() self.version = Version( task=self.task ) self.kwargs = { 'name': 'Photoshop', 'extensions': ['psd'], 'structure': ['Outputs'] } self.external_env = ExternalEnv(**self.kwargs)
def upload_thumbnail(task, thumbnail_full_path): """Uploads the given thumbnail for the given entity :param task: An instance of :class:`~stalker.models.entity.SimpleEntity` or a derivative. :param str thumbnail_full_path: A string which is showing the path of the thumbnail image """ extension = os.path.splitext(thumbnail_full_path)[-1] # move the file to the task thumbnail folder # and mimic StalkerPyramids output format thumbnail_original_file_name = 'thumbnail%s' % extension thumbnail_final_full_path = os.path.join(task.absolute_path, 'Thumbnail', thumbnail_original_file_name) try: os.makedirs(os.path.dirname(thumbnail_final_full_path)) except OSError: pass # # convert the thumbnail to jpg if it is a format that is not supported by # # browsers # ext_not_supported_by_browsers = ['.bmp', '.tga', '.tif', '.tiff', '.exr'] # if extension in ext_not_supported_by_browsers: # # use MediaManager to convert them # from anima.utils import MediaManager # mm = MediaManager() # thumbnail_full_path = mm.generate_image_thumbnail(thumbnail_full_path) import shutil shutil.copy(thumbnail_full_path, thumbnail_final_full_path) from stalker import Link, Version, Repository thumbnail_os_independent_path = \ Repository.to_os_independent_path(thumbnail_final_full_path) l_thumb = Link.query\ .filter(Link.full_path == thumbnail_os_independent_path).first() if not l_thumb: l_thumb = Link(full_path=thumbnail_os_independent_path, original_filename=thumbnail_original_file_name) task.thumbnail = l_thumb # get a version of this Task from stalker.db.session import DBSession v = Version.query.filter(Version.task == task).first() if v: for naming_parent in v.naming_parents: if not naming_parent.thumbnail: naming_parent.thumbnail = l_thumb DBSession.add(naming_parent) DBSession.add(l_thumb) DBSession.commit()
def accept(self): """overridden accept method """ if not self.name_lineEdit.is_valid: QtWidgets.QMessageBox.critical(self, 'Error', 'Please fix <b>name</b> field!') return name = self.name_lineEdit.text() custom_template = self.custom_template_plainTextEdit.toPlainText() filename_template_items = \ self.filename_templates_double_list_widget.secondary_items() filename_template_ids = [] for item in filename_template_items: filename_template_id = \ int(item.text().split('(')[-1].split(')')[0]) filename_template_ids.append(filename_template_id) from stalker import FilenameTemplate filename_templates = FilenameTemplate.query\ .filter(FilenameTemplate.id.in_(filename_template_ids)).all() from stalker import Structure from stalker.db.session import DBSession logged_in_user = self.get_logged_in_user() if self.mode == 'Create': # Create a new Structure try: structure = Structure(name=name, templates=filename_templates, custom_template=custom_template, created_by=logged_in_user) self.structure = structure DBSession.add(structure) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical(self, 'Error', str(e)) return elif self.mode == 'Update': # Update the structure try: self.structure.name = name self.structure.templates = filename_templates self.structure.custom_template = custom_template self.structure.updated_by = logged_in_user DBSession.add(self.structure) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical(self, 'Error', str(e)) return super(MainDialog, self).accept()
def test_tasks_are_correctly_scheduled(self): """testing if the tasks are correctly scheduled """ tjp_sched = TaskJugglerScheduler(compute_resources=True) from stalker import Studio test_studio = Studio( name='Test Studio', now=datetime.datetime(2013, 4, 16, 0, 0, tzinfo=pytz.utc) ) test_studio.start = \ datetime.datetime(2013, 4, 16, 0, 0, tzinfo=pytz.utc) test_studio.end = \ datetime.datetime(2013, 4, 30, 0, 0, tzinfo=pytz.utc) test_studio.daily_working_hours = 9 from stalker.db.session import DBSession DBSession.add(test_studio) tjp_sched.studio = test_studio tjp_sched.schedule() DBSession.commit() # check if the task and project timings are all adjusted assert \ datetime.datetime(2013, 4, 16, 9, 0, tzinfo=pytz.utc) == \ self.test_proj1.computed_start assert \ datetime.datetime(2013, 4, 24, 10, 0, tzinfo=pytz.utc) == \ self.test_proj1.computed_end assert \ datetime.datetime(2013, 4, 16, 9, 0, tzinfo=pytz.utc) == \ self.test_task1.computed_start assert \ datetime.datetime(2013, 4, 18, 16, 0, tzinfo=pytz.utc) == \ self.test_task1.computed_end assert \ sorted([self.test_user1, self.test_user2], key=lambda x: x.name) == \ sorted(self.test_task1.computed_resources, key=lambda x: x.name) assert \ datetime.datetime(2013, 4, 18, 16, 0, tzinfo=pytz.utc) == \ self.test_task2.computed_start assert \ datetime.datetime(2013, 4, 24, 10, 0, tzinfo=pytz.utc) == \ self.test_task2.computed_end assert len(self.test_task2.computed_resources) == 2 possible_resources = [ self.test_user2, self.test_user3, self.test_user4, self.test_user5 ] for r in self.test_task2.computed_resources: assert r in possible_resources
def accept(self): """the overridden accept method """ target_entity_type = self.target_entity_type_combo_box.currentText() if not self.name_line_edit.is_valid: QtWidgets.QMessageBox.critical(self, 'Error', 'Please fix <b>name</b> field!') return name = self.name_line_edit.text() path = self.path_line_edit.text() if path == '': QtWidgets.QMessageBox.critical(self, 'Error', 'Please fix <b>path</b> field!') return filename = self.filename_line_edit.text() if path == '': QtWidgets.QMessageBox.critical( self, 'Error', 'Please fix <b>filename</b> field!') return logged_in_user = self.get_logged_in_user() from stalker.db.session import DBSession if self.mode == 'Create': try: from stalker import FilenameTemplate # create a new FilenameTemplate ft = FilenameTemplate(name=name, path=path, filename=filename, target_entity_type=target_entity_type, created_by=logged_in_user) self.filename_template = ft DBSession.add(ft) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical(self, 'Error', str(e)) return elif self.mode == 'Update': try: self.filename_template.name = name self.filename_template.path = path self.filename_template.filename = filename self.filename_template.updated_by = logged_in_user DBSession.add(self.filename_template) DBSession.commit() except Exception as e: DBSession.rollback() QtWidgets.QMessageBox.critical(self, 'Error', str(e)) return super(MainDialog, self).accept()
def fix_task_status(self): """fix current task status """ from stalker import Task assert isinstance(self.task, Task) from anima import utils utils.fix_task_statuses(self.task) utils.fix_task_computed_time(self.task) from stalker.db.session import DBSession DBSession.add(self.task) DBSession.commit()
def create_ticket_statuses(): """creates the default ticket statuses """ from stalker import defaults, User # create as admin admin = User.query.filter(User.login == defaults.admin_name).first() # create statuses for Tickets ticket_names = defaults.ticket_status_names ticket_codes = defaults.ticket_status_codes create_entity_statuses('Ticket', ticket_names, ticket_codes, admin) # Again I hate doing this in this way from stalker import Type types = Type.query \ .filter_by(target_entity_type="Ticket") \ .all() t_names = [t.name for t in types] # create Ticket Types logger.debug("Creating Ticket Types") from stalker.db.session import DBSession if 'Defect' not in t_names: ticket_type_1 = Type( name='Defect', code='Defect', target_entity_type='Ticket', created_by=admin, updated_by=admin ) DBSession.add(ticket_type_1) if 'Enhancement' not in t_names: ticket_type_2 = Type( name='Enhancement', code='Enhancement', target_entity_type='Ticket', created_by=admin, updated_by=admin ) DBSession.add(ticket_type_2) from sqlalchemy.exc import IntegrityError try: DBSession.commit() except IntegrityError: DBSession.rollback() logger.debug("Ticket Types are already in the database!") else: # DBSession.flush() logger.debug("Ticket Types are created successfully")
def export_as(self, version): """the export action for max environment """ import MaxPlus # check if there is something selected if MaxPlus.SelectionManager.GetCount() < 1: raise RuntimeError("There is nothing selected to export") # check if this is the first version if version.is_published and not self.allow_publish_on_export: # it is not allowed to publish the first version (desdur) raise RuntimeError( 'It is not allowed to Publish while export!!!' '<br><br>' 'Export it normally. Then open the file and publish it.' ) # do not save if there are local files # self.check_external_files(version) # set the extension to max by default version.update_paths() version.extension = self.extensions[0] # define that this version is created with Max version.created_with = self.name # create the folder if it doesn't exists import os try: os.makedirs(version.absolute_path) except OSError: # already exists pass # workspace_path = os.path.dirname(version.absolute_path) workspace_path = version.absolute_path # self.create_workspace_file(workspace_path) # self.create_workspace_folders(workspace_path) # export the file MaxPlus.FileManager.SaveSelected(version.absolute_full_path) # save the version to database from stalker.db.session import DBSession DBSession.add(version) DBSession.commit() # create a local copy self.create_local_copy(version) return True
def test_to_os_independent_path_is_working_properly(self): """testing if to_os_independent_path class method is working properly """ from stalker.db.session import DBSession DBSession.add(self.test_repo) DBSession.commit() relative_part = 'some/path/to/a/file.ma' test_path = '%s/%s' % (self.test_repo.path, relative_part) from stalker import Repository assert Repository.to_os_independent_path(test_path) == \ '$REPO%s/%s' % (self.test_repo.id, relative_part)
def update_studio(request): """updates the studio """ studio_id = request.params.get('studio_id') studio = Studio.query.filter_by(id=studio_id).first() name = request.params.get('name', None) dwh = request.params.get('dwh', None) wh_mon_start = get_time(request, 'mon_start') wh_mon_end = get_time(request, 'mon_end') wh_tue_start = get_time(request, 'tue_start') wh_tue_end = get_time(request, 'tue_end') wh_wed_start = get_time(request, 'wed_start') wh_wed_end = get_time(request, 'wed_end') wh_thu_start = get_time(request, 'thu_start') wh_thu_end = get_time(request, 'thu_end') wh_fri_start = get_time(request, 'fri_start') wh_fri_end = get_time(request, 'fri_end') wh_sat_start = get_time(request, 'sat_start') wh_sat_end = get_time(request, 'sat_end') wh_sun_start = get_time(request, 'sun_start') wh_sun_end = get_time(request, 'sun_end') if studio and name and dwh: # update new studio studio.name=name studio.daily_working_hours=int(dwh) wh = WorkingHours() def set_wh_for_day(day, start, end): if start != end: wh[day] = [[start.seconds/60, end.seconds/60]] else: wh[day] = [] set_wh_for_day('mon', wh_mon_start, wh_mon_end) set_wh_for_day('tue', wh_tue_start, wh_tue_end) set_wh_for_day('wed', wh_wed_start, wh_wed_end) set_wh_for_day('thu', wh_thu_start, wh_thu_end) set_wh_for_day('fri', wh_fri_start, wh_fri_end) set_wh_for_day('sat', wh_sat_start, wh_sat_end) set_wh_for_day('sun', wh_sun_start, wh_sun_end) studio.working_hours = wh DBSession.add(studio) # Commit will be handled by the zope transaction extension return HTTPOk()
def test_timeLog_prevents_auto_flush_when_expanding_task_schedule_timing(self): """testing timeLog prevents auto flush when expanding task schedule_timing attribute """ from stalker.db.session import DBSession tlog1 = TimeLog(**self.kwargs) DBSession.add(tlog1) DBSession.commit() # create a new time log self.kwargs['start'] = self.kwargs['start'] + self.kwargs['duration'] tlog2 = TimeLog(**self.kwargs)
def test_versions_attribute_will_return_a_list_of_versions(self): """testing if the versions attribute is a list of Version instances related to the given links """ from stalker import Daily daily = Daily(name='Test Daily', project=self.test_project, status_list=self.daily_status_list) daily.links = [self.test_link1, self.test_link2] from stalker.db.session import DBSession DBSession.add(daily) DBSession.commit() assert daily.versions == [self.test_version1]
def test_version_number_attribute_is_automatically_generated(self): """testing if the version_number attribute is automatically generated """ self.assertEqual(self.test_version.version_number, 1) DBSession.add(self.test_version) DBSession.commit() new_version = Version(**self.kwargs) DBSession.add(new_version) DBSession.commit() self.assertEqual(self.test_version.task, new_version.task) self.assertEqual(self.test_version.take_name, new_version.take_name) self.assertEqual(new_version.version_number, 2) new_version = Version(**self.kwargs) DBSession.add(new_version) DBSession.commit() self.assertEqual(self.test_version.task, new_version.task) self.assertEqual(self.test_version.take_name, new_version.take_name) self.assertEqual(new_version.version_number, 3) new_version = Version(**self.kwargs) DBSession.add(new_version) DBSession.commit() self.assertEqual(self.test_version.task, new_version.task) self.assertEqual(self.test_version.take_name, new_version.take_name) self.assertEqual(new_version.version_number, 4)
def create_ticket_statuses(): """creates the default ticket statuses """ from stalker import User # create as admin admin = User.query.filter(User.login == defaults.admin_name).first() # create statuses for Tickets ticket_names = defaults.ticket_status_names ticket_codes = defaults.ticket_status_codes create_entity_statuses('Ticket', ticket_names, ticket_codes, admin) # Again I hate doing this in this way from stalker import Type types = Type.query \ .filter_by(target_entity_type="Ticket") \ .all() t_names = [t.name for t in types] # create Ticket Types logger.debug("Creating Ticket Types") if 'Defect' not in t_names: ticket_type_1 = Type( name='Defect', code='Defect', target_entity_type='Ticket', created_by=admin, updated_by=admin ) DBSession.add(ticket_type_1) if 'Enhancement' not in t_names: ticket_type_2 = Type( name='Enhancement', code='Enhancement', target_entity_type='Ticket', created_by=admin, updated_by=admin ) DBSession.add(ticket_type_2) try: DBSession.commit() except IntegrityError: DBSession.rollback() logger.debug("Ticket Types are already in the database!") else: # DBSession.flush() logger.debug("Ticket Types are created successfully")
def create_entity_statuses(entity_type="", status_names=None, status_codes=None, user=None): """creates the default task statuses """ if not entity_type: raise ValueError("Please supply entity_type") if not status_names: raise ValueError("Please supply status names") if not status_codes: raise ValueError("Please supply status codes") # create statuses for entity from stalker import Status, StatusList logger.debug("Creating %s Statuses" % entity_type) statuses = Status.query.filter(Status.name.in_(status_names)).all() status_names_in_db = map(lambda x: x.name, statuses) for name, code in zip(status_names, status_codes): if name not in status_names_in_db: logger.debug("Creating Status: %s (%s)" % (name, code)) new_status = Status(name=name, code=code, created_by=user, updated_by=user) statuses.append(new_status) DBSession.add(new_status) # create the Status List status_list = StatusList.query.filter(StatusList.target_entity_type == entity_type).first() if status_list is None: logger.debug("No %s Status List found, creating new!" % entity_type) status_list = StatusList( name="%s Statuses" % entity_type, target_entity_type=entity_type, created_by=user, updated_by=user ) else: logger.debug("%s Status List already created, updating statuses" % entity_type) status_list.statuses = statuses DBSession.add(status_list) try: DBSession.commit() except IntegrityError as e: logger.debug("error in DBSession.commit, rolling back: %s" % e) DBSession.rollback() else: logger.debug("Created %s Statuses successfully" % entity_type) DBSession.flush()
def test_number_attribute_is_automatically_increased(self): """testing if the number attribute is automatically increased """ # create two new tickets ticket1 = Ticket(**self.kwargs) DBSession.add(ticket1) DBSession.commit() ticket2 = Ticket(**self.kwargs) DBSession.add(ticket2) DBSession.commit() self.assertEqual(ticket1.number + 1, ticket2.number) self.assertEqual(ticket1.number, 2) self.assertEqual(ticket2.number, 3)
def test_email_argument_should_be_a_unique_value(self): """testing if the email argument should be a unique value """ # this test should include a database test_email = "*****@*****.**" self.kwargs["login"] = "******" self.kwargs["email"] = test_email user1 = User(**self.kwargs) DBSession.add(user1) DBSession.commit() self.kwargs["login"] = "******" user2 = User(**self.kwargs) DBSession.add(user2) self.assertRaises(Exception, DBSession.commit)
def test_login_argument_should_be_a_unique_value(self): """testing if the login argument should be a unique value """ # this test should include a database test_login = '******' self.kwargs['login'] = test_login self.kwargs['email'] = "*****@*****.**" user1 = User(**self.kwargs) DBSession.add(user1) DBSession.commit() self.kwargs['email'] = "*****@*****.**" user2 = User(**self.kwargs) DBSession.add(user2) self.assertRaises(Exception, DBSession.commit)
def setUp(self): self.config = testing.setUp() db.setup({'sqlalchemy.url': 'sqlite:///:memory:'}) self.test_status1 = Status(name='Test Status 1', code='TS1') self.test_status2 = Status(name='Test Status 2', code='TS2') self.test_status3 = Status(name='Test Status 3', code='TS3') self.test_project_status_list = StatusList( target_entity_type='Project', statuses=[ self.test_status1, self.test_status2, self.test_status3 ] ) self.test_repo = Repository( name='Test Repository', windows_path='T:/', linux_path='/mnt/T', osx_path='/Volumes/T' ) self.test_project = Project( name='Test Project 1', code='TP1', status_list=self.test_project_status_list, repository=self.test_repo ) DBSession.add(self.test_project) transaction.commit() DBSession.add(self.test_project) self.params = { 'mode': 'CREATE' } self.matchdict = { 'project_id': self.test_project.id } self.request = testing.DummyRequest(params=self.params) self.request.matchdict = self.matchdict
def test_nice_name_attribute_is_working_properly(self): """testing if the nice_name attribute is working properly """ # for self.test_version self.assertEqual(self.test_version.naming_parents, [self.test_shot1, self.test_task1]) # for a new version of a task task1 = Task(name="Test Task 1", project=self.test_project, status_list=self.test_task_status_list) task2 = Task(name="Test Task 2", parent=task1, status_list=self.test_task_status_list) task3 = Task(name="Test Task 3", parent=task2, status_list=self.test_task_status_list) DBSession.add_all([task1, task2, task3]) DBSession.commit() version1 = Version(task=task3, take_name="Take1") DBSession.add(version1) DBSession.commit() self.assertEqual( version1.nice_name, "%s_%s_%s_%s" % (task1.nice_name, task2.nice_name, task3.nice_name, version1.take_name) ) # for a an asset version asset_statuses = StatusList( target_entity_type="Asset", statuses=[self.test_status1, self.test_status2, self.test_status3] ) character_type = Type(target_entity_type="Asset", name="Character", code="Char") asset1 = Asset(name="Asset1", code="Asset1", parent=task1, status_list=asset_statuses, type=character_type) version2 = Version(task=asset1) self.assertEqual(version2.nice_name, "%s_%s" % (asset1.nice_name, version2.take_name)) # for a version of a task of a shot shot2 = Shot(name="SH002", code="SH002", parent=task3, status_list=self.test_shot_status_list) task4 = Task(name="Test Task 4", parent=shot2, status_list=self.test_task_status_list) version3 = Version(task=task4) self.assertEqual(version3.nice_name, "%s_%s_%s" % (shot2.nice_name, task4.nice_name, version3.take_name)) # for an asset of a shot asset2 = Asset(name="Asset2", code="Asset2", parent=shot2, status_list=asset_statuses, type=character_type) version4 = Version(task=asset2) self.assertEqual(version4.nice_name, "%s_%s" % (asset2.nice_name, version4.take_name))
def login(self): """does the nasty details for user to login """ # check the given user password from stalker import User # get the user first login = self.login_or_email_lineEdit.text() password = self.password_lineEdit.text() # check with the login or email attribute user = User.query \ .filter(or_(User.login == login, User.email == login)) \ .first() if user: self.success = user.check_password(password) if self.success: from stalker.models.auth import LocalSession session = LocalSession() session.store_user(user) session.save() # also store a log import datetime from stalker.models.auth import LOGIN, AuthenticationLog al = AuthenticationLog( user=user, date=datetime.datetime.now(), action=LOGIN ) from stalker.db.session import DBSession DBSession.add(al) DBSession.commit() self.accept() else: QtWidgets.QMessageBox.critical( self, "Error", "login or password is incorrect" )
def test_absolute_full_path_works_properly(self): """testing if the absolute_full_path attribute works properly """ ft = FilenameTemplate( name="Task Filename Template", target_entity_type="Task", path="{{project.code}}/{%- for parent_task in parent_tasks -%}" "{{parent_task.nice_name}}/{%- endfor -%}", filename="{{task.nice_name}}_{{version.take_name}}" '_v{{"%03d"|format(version.version_number)}}{{extension}}', ) self.test_project.structure.templates.append(ft) new_version1 = Version(**self.kwargs) DBSession.add(new_version1) DBSession.commit() new_version1.update_paths() new_version1.extension = ".ma" self.assertEqual(new_version1.extension, ".ma") self.assertEqual(new_version1.absolute_full_path, "/mnt/T/tp/SH001/Task1/Task1_TestTake_v001.ma")
def test_inequality_operator(self): """testing inequality of two Version instances """ new_version1 = Version(**self.kwargs) DBSession.add(new_version1) DBSession.commit() new_version2 = Version(**self.kwargs) DBSession.add(new_version2) DBSession.commit() new_version3 = Version(**self.kwargs) DBSession.add(new_version3) DBSession.commit() new_version4 = Version(**self.kwargs) DBSession.add(new_version4) DBSession.commit() new_version5 = Version(**self.kwargs) DBSession.add(new_version5) DBSession.commit() new_version1.is_published = True new_version3.is_published = True new_version4.is_published = True self.assertTrue(new_version1 != new_version2) self.assertTrue(new_version1 != new_version3) self.assertTrue(new_version1 != new_version4) self.assertTrue(new_version1 != new_version5) self.assertTrue(new_version2 != new_version3) self.assertTrue(new_version2 != new_version4) self.assertTrue(new_version2 != new_version5) self.assertTrue(new_version3 != new_version4) self.assertTrue(new_version3 != new_version5) self.assertTrue(new_version4 != new_version5)
def __create_admin__(): """creates the admin """ from stalker.models.auth import User from stalker.models.department import Department # check if there is already an admin in the database admin = User.query.filter_by(name=defaults.admin_name).first() if admin: # there should be an admin user do nothing logger.debug("there is an admin already") return logger.debug("creating the default administrator user") # create the admin department admin_department = Department.query.filter_by(name=defaults.admin_department_name).first() if not admin_department: admin_department = Department(name=defaults.admin_department_name) DBSession.add(admin_department) # create the admins group from stalker.models.auth import Group admins_group = Group.query.filter_by(name=defaults.admin_group_name).first() if not admins_group: admins_group = Group(name=defaults.admin_group_name) DBSession.add(admins_group) # # create the admin user # admin = User.query \ # .filter_by(name=defaults.admin_name) \ # .first() # if not admin: admin = User( name=defaults.admin_name, login=defaults.admin_login, password=defaults.admin_password, email=defaults.admin_email, departments=[admin_department], groups=[admins_group], ) admin.created_by = admin admin.updated_by = admin # update the department as created and updated by admin user admin_department.created_by = admin admin_department.updated_by = admin admins_group.created_by = admin admins_group.updated_by = admin DBSession.add(admin) DBSession.commit()
def test_start_end_and_duration_values_are_rounded_to_the_Studio_timing_resolution(self): """testing if the start and end dates are rounded to the Studio timing_resolution """ from stalker.models.studio import Studio studio = Studio( name='Test Studio', timing_resolution=datetime.timedelta(minutes=5) ) DBSession.add(studio) DBSession.commit() self.kwargs['start'] = datetime.datetime(2013, 3, 22, 2, 38, 55, 531) self.kwargs['end'] = datetime.datetime(2013, 3, 24, 16, 46, 32, 102) new_foo_obj = DateRangeMixFooMixedInClass(**self.kwargs) # check the start expected_start = datetime.datetime(2013, 3, 22, 2, 40) self.assertEqual(new_foo_obj.start, expected_start) # check the end expected_end = datetime.datetime(2013, 3, 24, 16, 45) self.assertEqual(new_foo_obj.end, expected_end) # check the duration self.assertEqual(new_foo_obj.duration, expected_end - expected_start)
def update_version_inputs(self, parent_ref=None): """updates the references list of the current version :param parent_ref: the parent ref, if given will override the given version argument and a Version instance will be get from the given parent_ref.path. """ logger.debug('parent_ref: %s' % parent_ref) logger.debug('get a version') if not parent_ref: logger.debug('got no parent_ref') version = self.get_current_version() else: logger.debug('have a parent_ref') version = self.get_version_from_full_path(parent_ref.path) if version: logger.debug('got a version: %s' % version.absolute_full_path) # use the original version if it is a Repr version from anima.representation import Representation if Representation.repr_separator in version.take_name \ and version.parent: version = version.parent logger.debug( 'this is a representation switching to its parent: %s' % version ) # update the reference list referenced_versions = self.get_referenced_versions(parent_ref) version.inputs = referenced_versions # commit data to the database from stalker.db.session import DBSession DBSession.add(version) DBSession.commit()
def test_timeLog_creation_for_a_child_task(self): """testing TimeLog creation for a child task which has a couple of parent tasks """ dt = datetime.datetime td = datetime.timedelta parent_task1 = Task( name="Parent Task 1", project=self.test_project, status_list=self.test_task_status_list, ) parent_task2 = Task( name="Parent Task 2", project=self.test_project, status_list=self.test_task_status_list, ) child_task1 = Task( name="Child Task 1", project=self.test_project, status_list=self.test_task_status_list, resources=[self.test_resource1] ) child_task2 = Task( name="Child Task 1", project=self.test_project, status_list=self.test_task_status_list, resources=[self.test_resource2] ) # Task hierarchy # +-> p1 # | | # | +-> p2 # | | | # | | +-> c1 # | | # | +-> c2 # | # +-> self.test_task1 parent_task2.parent = parent_task1 child_task2.parent = parent_task1 child_task1.parent = parent_task2 from stalker.db.session import DBSession self.assertEqual(parent_task1.total_logged_seconds, 0) self.assertEqual(parent_task2.total_logged_seconds, 0) self.assertEqual(child_task1.total_logged_seconds, 0) self.assertEqual(child_task2.total_logged_seconds, 0) # now create a time log for child_task2 tlog1 = TimeLog( task=child_task2, resource=child_task2.resources[0], start=dt(2013, 7, 31, 10, 0), end=dt(2013, 7, 31, 19, 0) ) # before commit self.assertEqual(parent_task1.total_logged_seconds, 9 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 0) self.assertEqual(child_task1.total_logged_seconds, 0) self.assertEqual(child_task2.total_logged_seconds, 9 * 3600) # commit changes DBSession.add(tlog1) DBSession.commit() # after commit it should not change self.assertEqual(parent_task1.total_logged_seconds, 9 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 0) self.assertEqual(child_task1.total_logged_seconds, 0) self.assertEqual(child_task2.total_logged_seconds, 9 * 3600) # add a new tlog to child_task2 and commit it # now create a time log for child_task2 tlog2 = TimeLog( task=child_task2, resource=child_task2.resources[0], start=dt(2013, 7, 31, 19, 0), end=dt(2013, 7, 31, 22, 0) ) self.assertEqual(parent_task1.total_logged_seconds, 12 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 0) self.assertEqual(child_task1.total_logged_seconds, 0) self.assertEqual(child_task2.total_logged_seconds, 12 * 3600) # commit changes DBSession.add(tlog2) DBSession.commit() self.assertEqual(parent_task1.total_logged_seconds, 12 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 0) self.assertEqual(child_task1.total_logged_seconds, 0) self.assertEqual(child_task2.total_logged_seconds, 12 * 3600) # add a new time log to child_task1 and commit it tlog3 = TimeLog( task=child_task1, resource=child_task1.resources[0], start=dt(2013, 7, 31, 10, 0), end=dt(2013, 7, 31, 19, 0) ) self.assertEqual(parent_task1.total_logged_seconds, 21 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 9 * 3600) self.assertEqual(child_task1.total_logged_seconds, 9 * 3600) self.assertEqual(child_task2.total_logged_seconds, 12 * 3600) # commit changes DBSession.add(tlog3) DBSession.commit() self.assertEqual(parent_task1.total_logged_seconds, 21 * 3600) self.assertEqual(parent_task2.total_logged_seconds, 9 * 3600) self.assertEqual(child_task1.total_logged_seconds, 9 * 3600) self.assertEqual(child_task2.total_logged_seconds, 12 * 3600)
def accept(self): """overridden accept method """ # get the info task = self.tasks_combo_box.currentTask() resource = self.get_current_resource() # war the user if the resource is not the logged_in_user if resource != self.logged_in_user: msg_box = QtWidgets.QMessageBox(self) msg_box.setWindowTitle( 'Entering TimeLog On Behalf of Somebody Else' ) msg_box.setText( "You're entering a TimeLog on behalf of somebody else???" ) accept_button = msg_box.addButton( 'Accept the responsibility', QtWidgets.QMessageBox.AcceptRole ) cancel_button = msg_box.addButton( 'Cancel', QtWidgets.QMessageBox.RejectRole ) msg_box.setDefaultButton(cancel_button) msg_box.exec_() clicked_button = msg_box.clickedButton() msg_box.deleteLater() if clicked_button == cancel_button: return description = self.description_plain_text_edit.toPlainText() revision_cause_text = \ self.revision_type_combo_box.currentText().replace(' ', '_') is_complete = self.set_as_complete_radio_button.isChecked() submit_to_final_review = \ self.submit_for_final_review_radio_button.isChecked() # get the revision Types from stalker import Type revision_type = Type.query\ .filter(Type.target_entity_type == 'Note')\ .filter(Type.name == revision_cause_text)\ .first() date = self.calendar_widget.selectedDate() start = self.start_time_edit.time() end = self.end_time_edit.time() # construct proper datetime.DateTime instances import datetime start_date = datetime.datetime( date.year(), date.month(), date.day(), start.hour(), start.minute() ) end_date = datetime.datetime( date.year(), date.month(), date.day(), end.hour(), end.minute() ) today_midnight = datetime.datetime.now().replace( hour=23, minute=59, second=59, microsecond=999 ) # raise an error if the user is trying to enter a TimeLog to the future if start_date > today_midnight or end_date > today_midnight: QtWidgets.QMessageBox.critical( self, 'Error', 'Gelecege TimeLog giremezsiniz!!!', ) return # convert them to utc from anima.utils import local_to_utc utc_start_date = local_to_utc(start_date) utc_end_date = local_to_utc(end_date) # create a TimeLog # print('Task : %s' % task.name) # print('Resource : %s' % resource.name) # print('utc_start_date: %s' % utc_start_date) # print('utc_end_date : %s' % utc_end_date) # now if we are not using extra time just create the TimeLog from stalker import TimeLog from stalker.db.session import DBSession from stalker.exceptions import (OverBookedError, DependencyViolationError) utc_now = local_to_utc(datetime.datetime.now()) # TODO: Remove this in a later version import stalker from distutils.version import LooseVersion if LooseVersion(stalker.__version__) >= LooseVersion('0.2.18'): # inject timezone info import pytz utc_start_date = utc_start_date.replace(tzinfo=pytz.utc) utc_end_date = utc_end_date.replace(tzinfo=pytz.utc) utc_now = utc_now.replace(tzinfo=pytz.utc) from sqlalchemy.exc import IntegrityError if not self.timelog: try: new_time_log = TimeLog( task=task, resource=resource, start=utc_start_date, end=utc_end_date, description=description, date_created=utc_now ) except (OverBookedError, DependencyViolationError) as e: # inform the user that it can not do that QtWidgets.QMessageBox.critical( self, 'Error', '%s' % e ) DBSession.rollback() return try: DBSession.add(new_time_log) DBSession.commit() self.timelog_created = True except IntegrityError as e: DBSession.rollback() QtWidgets.QMessageBox.critical( self, 'Error', 'Database Error!!!' '<br>' '%s' % e ) return else: # just update the date values self.timelog.start = utc_start_date self.timelog.end = utc_end_date self.timelog.date_updated = utc_now DBSession.add(self.timelog) DBSession.commit() if self.no_time_left: # we have no time left so automatically extend the task from stalker import Task schedule_timing, schedule_unit = \ task.least_meaningful_time_unit( task.total_logged_seconds ) if schedule_timing != 0: task.schedule_timing = schedule_timing task.schedule_unit = schedule_unit # also create a Note from stalker import Note new_note = Note( content='Extending timing of the task <b>%s h %s min.</b>' % ( self.extended_hours, self.extended_minutes ), type=revision_type, created_by=self.logged_in_user, date_created=utc_now ) DBSession.add(new_note) task.notes.append(new_note) try: DBSession.commit() except IntegrityError as e: QtWidgets.QMessageBox.critical( self, 'Error', 'Database Error!!!' '<br>' '%s' % e ) DBSession.rollback() return if is_complete: # set the status to complete from stalker import Type, Status status_cmpl = Status.query.filter(Status.code == 'CMPL').first() forced_status_type = \ Type.query.filter(Type.name == 'Forced Status').first() # also create a Note from stalker import Note new_note = Note( content='%s has changed this task status to Completed' % resource.name, type=forced_status_type, created_by=self.logged_in_user, date_created=utc_now ) DBSession.add(new_note) task.notes.append(new_note) task.status = status_cmpl DBSession.commit() elif submit_to_final_review: # clip the Task timing to current time logs from stalker import Task schedule_timing, schedule_unit = \ task.least_meaningful_time_unit( task.total_logged_seconds ) task.schedule_timing = schedule_timing task.schedule_unit = schedule_unit DBSession.add(task) try: DBSession.commit() except IntegrityError as e: QtWidgets.QMessageBox.critical( self, 'Error', 'Database Error!!!' '<br>' '%s' % e ) DBSession.rollback() return # request a review reviews = task.request_review() for review in reviews: review.created_by = review.updated_by = self.logged_in_user review.date_created = utc_now review.date_updated = utc_now DBSession.add_all(reviews) # and create a Note for the Task request_review_note_type = \ Type.query\ .filter(Type.target_entity_type == 'Note')\ .filter(Type.name == 'Request Review')\ .first() from stalker import Note request_review_note = Note( type=request_review_note_type, created_by=self.logged_in_user, date_created=utc_now ) DBSession.add(request_review_note) DBSession.add(task) task.notes.append(request_review_note) try: DBSession.commit() except IntegrityError as e: DBSession.rollback() QtWidgets.QMessageBox.critical( self, 'Error', 'Database Error!!!' '<br>' '%s' % e ) return # Fix statuses from anima import utils utils.fix_task_statuses(task) try: DBSession.commit() except IntegrityError as e: DBSession.rollback() QtWidgets.QMessageBox.critical( self, 'Error', 'Database Error!!!' '<br>' '%s' % e ) return # if nothing bad happens close the dialog super(MainDialog, self).accept()
def test_number_attribute_is_not_created_per_project(self): """testing if the number attribute is not created per project and continues to increase for every created ticket """ proj1 = Project( name='Test Project 1', code='TP1', repository=self.test_repo, status_list=self.test_project_status_list ) proj2 = Project( name='Test Project 2', code='TP2', repository=self.test_repo, status_list=self.test_project_status_list ) proj3 = Project( name='Test Project 3', code='TP3', repository=self.test_repo, status_list=self.test_project_status_list ) p1_t1 = Ticket(project=proj1) DBSession.add(p1_t1) DBSession.commit() self.assertEqual(p1_t1.number, 2) p1_t2 = Ticket(project=proj1) DBSession.add(p1_t2) DBSession.commit() self.assertEqual(p1_t2.number, 3) p2_t1 = Ticket(project=proj2) DBSession.add(p2_t1) DBSession.commit() self.assertEqual(p2_t1.number, 4) p1_t3 = Ticket(project=proj1) DBSession.add(p1_t3) DBSession.commit() self.assertEqual(p1_t3.number, 5) p3_t1 = Ticket(project=proj3) DBSession.add(p3_t1) DBSession.commit() self.assertEqual(p3_t1.number, 6) p2_t2 = Ticket(project=proj2) DBSession.add(p2_t2) DBSession.commit() self.assertEqual(p2_t2.number, 7) p3_t2 = Ticket(project=proj3) DBSession.add(p3_t2) DBSession.commit() self.assertEqual(p3_t2.number, 8) p2_t3 = Ticket(project=proj2) DBSession.add(p2_t3) DBSession.commit() self.assertEqual(p2_t3.number, 9)
def setUp(self): """set up the test """ # create the db DBSession.remove() db.setup() # db.init() # we just need statuses so create them instead of initializing the db db.create_ticket_statuses() db.create_entity_statuses(entity_type='Task', status_names=defaults.task_status_names, status_codes=defaults.task_status_codes) db.create_entity_statuses(entity_type='Asset', status_names=defaults.task_status_names, status_codes=defaults.task_status_codes) db.create_entity_statuses(entity_type='Shot', status_names=defaults.task_status_names, status_codes=defaults.task_status_codes) db.create_entity_statuses(entity_type='Sequence', status_names=defaults.task_status_names, status_codes=defaults.task_status_codes) db.create_entity_statuses(entity_type='Review', status_names=defaults.review_status_names, status_codes=defaults.review_status_codes) # create statuses self.test_status1 = Status(name='N', code='N') self.test_status2 = Status(name='R', code='R') # get the ticket types ticket_types = Type.query \ .filter(Type.target_entity_type == 'Ticket').all() self.ticket_type_1 = ticket_types[0] self.ticket_type_2 = ticket_types[1] # create a User self.test_user = User( name='Test User', login='******', email='*****@*****.**', password='******' ) # create a Repository self.test_repo = Repository(name="Test Repo") # create a Project Type self.test_project_type = Type( name='Commercial Project', code='comm', target_entity_type=Project, ) # create a Project StatusList self.test_project_status1 = Status(name='PrjStat1', code='PrjStat1') self.test_project_status2 = Status(name='PrjStat2', code='PrjStat2') self.test_project_status_list = StatusList( name="Project Status List", target_entity_type=Project, statuses=[ self.test_project_status1, self.test_project_status2, ] ) self.test_task_status_list = StatusList.query\ .filter_by(target_entity_type='Task').first() # create a Project self.test_project = Project( name="Test Project 1", code="TEST_PROJECT_1", type=self.test_project_type, repository=self.test_repo, status_list=self.test_project_status_list ) # create an Asset self.test_asset_status_list = StatusList.query\ .filter_by(target_entity_type='Asset').first() self.test_asset_type = Type( name='Character Asset', code='char', target_entity_type=Asset ) self.test_asset = Asset( name="Test Asset", code='ta', project=self.test_project, status_list=self.test_asset_status_list, type=self.test_asset_type ) # create a Task self.test_task = Task( name="Modeling of Asset 1", resources=[self.test_user], status_list=self.test_task_status_list, parent=self.test_asset ) # create a Version self.test_version_status_list = StatusList( name='Version Statuses', target_entity_type=Version, statuses=[self.test_status1, self.test_status2] ) self.test_version = Version( name='Test Version', task=self.test_task, status_list=self.test_version_status_list, version=1, full_path='some/path' ) # create the Ticket self.kwargs = { 'project': self.test_project, 'links': [self.test_version], 'summary': 'This is a test ticket', 'description': 'This is the long description', 'priority': 'TRIVIAL', 'reported_by': self.test_user, } self.test_ticket = Ticket(**self.kwargs) DBSession.add(self.test_ticket) DBSession.commit() # get the Ticket Statuses self.status_new = Status.query.filter_by(name='New').first() self.status_accepted = Status.query.filter_by(name='Accepted').first() self.status_assigned = Status.query.filter_by(name='Assigned').first() self.status_reopened = Status.query.filter_by(name='Reopened').first() self.status_closed = Status.query.filter_by(name='Closed').first()
def register(class_): """Registers the given class to the database. It is mainly used to create the :class:`.Action`\ s needed for the :class:`.User`\ s and :class:`.Group`\ s to be able to interact with the given class. Whatever class you have created needs to be registered. Example, lets say that you have a data class which is specific to your studio and it is not present in Stalker Object Model (SOM), so you need to extend SOM with a new data type. Here is a simple Data class inherited from the :class:`.SimpleEntity` class (which is the simplest class you should inherit your classes from or use more complex classes down to the hierarchy):: from sqlalchemy import Column, Integer, ForeignKey from stalker.models.entity import SimpleEntity class MyDataClass(SimpleEntity): '''This is an example class holding a studio specific data which is not present in SOM. ''' __tablename__ = 'MyData' __mapper_arguments__ = {'polymorphic_identity': 'MyData'} my_data_id = Column('id', Integer, ForeignKey('SimpleEntities.c.id'), primary_key=True) Now because Stalker is using Pyramid authorization mechanism it needs to be able to have an :class:`.Permission` about your new class, so you can assign this :class;`.Permission` to your :class:`.User`\ s or :class:`.Group`\ s. So you ned to register your new class with :func:`stalker.db.register` like shown below:: from stalker import db db.register(MyDataClass) This will create the necessary Actions in the 'Actions' table on your database, then you can create :class:`.Permission`\ s and assign these to your :class:`.User`\ s and :class:`.Group`\ s so they are Allowed or Denied to do the specified Action. :param class_: The class itself that needs to be registered. """ from stalker.models.auth import Permission # create the Permissions permissions_db = Permission.query.all() if not isinstance(class_, type): raise TypeError("To register a class please supply the class itself.") # register the class name to entity_types table from stalker import EntityType, StatusMixin, DateRangeMixin, ReferenceMixin, ScheduleMixin class_name = class_.__name__ if not EntityType.query.filter_by(name=class_name).first(): new_entity_type = EntityType(class_name) # update attributes if issubclass(class_, StatusMixin): new_entity_type.statusable = True if issubclass(class_, DateRangeMixin): new_entity_type.dateable = True if issubclass(class_, ScheduleMixin): new_entity_type.schedulable = True if issubclass(class_, ReferenceMixin): new_entity_type.accepts_references = True DBSession.add(new_entity_type) for action in defaults.actions: for access in ["Allow", "Deny"]: permission_obj = Permission(access, action, class_name) if permission_obj not in permissions_db: DBSession.add(permission_obj) try: DBSession.commit() except IntegrityError: DBSession.rollback()
def setUp(self): """setup the test """ # setup a test database self.TEST_DATABASE_URI = "sqlite:///:memory:" db.setup() db.init() # need to have some test object for # a department self.test_department1 = Department(name="Test Department 1") self.test_department2 = Department(name="Test Department 2") self.test_department3 = Department(name="Test Department 3") DBSession.add_all([self.test_department1, self.test_department2, self.test_department3]) # a couple of groups self.test_group1 = Group(name="Test Group 1") self.test_group2 = Group(name="Test Group 2") self.test_group3 = Group(name="Test Group 3") DBSession.add_all([self.test_group1, self.test_group2, self.test_group3]) # a couple of statuses self.test_status1 = Status(name="Completed", code="CMPLT") self.test_status2 = Status(name="Work In Progress", code="WIP") self.test_status3 = Status(name="Waiting To Start", code="WTS") self.test_status4 = Status(name="Pending Review", code="PRev") DBSession.add_all([self.test_status1, self.test_status2, self.test_status3, self.test_status4]) # a project status list self.project_status_list = StatusList( name="Project Status List", statuses=[self.test_status1, self.test_status2, self.test_status3, self.test_status4], target_entity_type=Project, ) # a repository type self.test_repository_type = Type(name="Test", code="test", target_entity_type=Repository) # a repository self.test_repository = Repository(name="Test Repository", type=self.test_repository_type) # a project type self.commercial_project_type = Type(name="Commercial Project", code="comm", target_entity_type=Project) # a couple of projects self.test_project1 = Project( name="Test Project 1", code="tp1", status_list=self.project_status_list, type=self.commercial_project_type, repository=self.test_repository, ) self.test_project2 = Project( name="Test Project 2", code="tp2", status_list=self.project_status_list, type=self.commercial_project_type, repository=self.test_repository, ) self.test_project3 = Project( name="Test Project 3", code="tp3", status_list=self.project_status_list, type=self.commercial_project_type, repository=self.test_repository, ) DBSession.add_all([self.test_project1, self.test_project2, self.test_project3]) # a task status list self.task_status_list = StatusList.query.filter_by(target_entity_type="Task").first() # a couple of tasks self.test_task1 = Task(name="Test Task 1", status_list=self.task_status_list, project=self.test_project1) self.test_task2 = Task(name="Test Task 2", status_list=self.task_status_list, project=self.test_project1) self.test_task3 = Task(name="Test Task 3", status_list=self.task_status_list, project=self.test_project2) self.test_task4 = Task(name="Test Task 4", status_list=self.task_status_list, project=self.test_project3) DBSession.add_all([self.test_task1, self.test_task2, self.test_task3, self.test_task4]) # for task1 self.test_version1 = Version(task=self.test_task1, full_path="some/path") DBSession.add(self.test_version1) self.test_version2 = Version(task=self.test_task1, full_path="some/path") DBSession.add(self.test_version2) self.test_version3 = Version(task=self.test_task1, full_path="some/path") DBSession.add(self.test_version3) # for task2 self.test_version4 = Version(task=self.test_task2, full_path="some/path") DBSession.add(self.test_version4) self.test_version5 = Version(task=self.test_task2, full_path="some/path") DBSession.add(self.test_version5) self.test_version6 = Version(task=self.test_task2, full_path="some/path") DBSession.add(self.test_version6) # for task3 self.test_version7 = Version(task=self.test_task3, full_path="some/path") DBSession.add(self.test_version7) self.test_version8 = Version(task=self.test_task3, full_path="some/path") DBSession.add(self.test_version8) self.test_version9 = Version(task=self.test_task3, full_path="some/path") DBSession.add(self.test_version9) # for task4 self.test_version10 = Version(task=self.test_task4, full_path="some/path") DBSession.add(self.test_version10) self.test_version11 = Version(task=self.test_task4, full_path="some/path") DBSession.add(self.test_version11) self.test_version12 = Version(task=self.test_task4, full_path="some/path") DBSession.add(self.test_version12) # ********************************************************************* # Tickets # ********************************************************************* # no need to create status list for tickets cause we have a database # set up an running so it will be automatically linked # tickets for version1 self.test_ticket1 = Ticket(project=self.test_project1, links=[self.test_version1]) DBSession.add(self.test_ticket1) # set it to closed self.test_ticket1.resolve() # create a new ticket and leave it open self.test_ticket2 = Ticket(project=self.test_project1, links=[self.test_version1]) DBSession.add(self.test_ticket2) # create a new ticket and close and then reopen it self.test_ticket3 = Ticket(project=self.test_project1, links=[self.test_version1]) DBSession.add(self.test_ticket3) self.test_ticket3.resolve() self.test_ticket3.reopen() # ********************************************************************* # tickets for version2 # create a new ticket and leave it open self.test_ticket4 = Ticket(project=self.test_project1, links=[self.test_version2]) DBSession.add(self.test_ticket4) # create a new Ticket and close it self.test_ticket5 = Ticket(project=self.test_project1, links=[self.test_version2]) DBSession.add(self.test_ticket5) self.test_ticket5.resolve() # create a new Ticket and close it self.test_ticket6 = Ticket(project=self.test_project1, links=[self.test_version3]) DBSession.add(self.test_ticket6) self.test_ticket6.resolve() # ********************************************************************* # tickets for version3 # create a new ticket and close it self.test_ticket7 = Ticket(project=self.test_project1, links=[self.test_version3]) DBSession.add(self.test_ticket7) self.test_ticket7.resolve() # create a new ticket and close it self.test_ticket8 = Ticket(project=self.test_project1, links=[self.test_version3]) DBSession.add(self.test_ticket8) self.test_ticket8.resolve() # ********************************************************************* # tickets for version4 # create a new ticket and close it self.test_ticket9 = Ticket(project=self.test_project1, links=[self.test_version4]) DBSession.add(self.test_ticket9) self.test_ticket9.resolve() # no tickets for any other version # ********************************************************************* # a status list for sequence self.sequence_status_list = StatusList.query.filter_by(target_entity_type="Sequence").first() # a couple of sequences self.test_sequence1 = Sequence( name="Test Seq 1", code="ts1", project=self.test_project1, status_list=self.sequence_status_list ) self.test_sequence2 = Sequence( name="Test Seq 2", code="ts2", project=self.test_project1, status_list=self.sequence_status_list ) self.test_sequence3 = Sequence( name="Test Seq 3", code="ts3", project=self.test_project1, status_list=self.sequence_status_list ) self.test_sequence4 = Sequence( name="Test Seq 4", code="ts4", project=self.test_project1, status_list=self.sequence_status_list ) DBSession.add_all([self.test_sequence1, self.test_sequence2, self.test_sequence3, self.test_sequence4]) # a test admin # self.test_admin = User( # name='Admin', # login='******', # email='*****@*****.**', # password='******' # ) self.test_admin = User.query.filter_by(name=defaults.admin_name).first() self.assertIsNotNone(self.test_admin) # create the default values for parameters self.kwargs = { "name": "Erkan Ozgur Yilmaz", "login": "******", "description": "this is a test user", "password": "******", "email": "*****@*****.**", "departments": [self.test_department1], "groups": [self.test_group1, self.test_group2], "created_by": self.test_admin, "updated_by": self.test_admin, } # create a proper user object self.test_user = User(**self.kwargs) DBSession.add(self.test_user) DBSession.commit() # just change the kwargs for other tests self.kwargs["name"] = "some other name" self.kwargs["email"] = "*****@*****.**"