def test_delete_art(self): mediafile = self._mediafile_fixture('empty') mediafile.art = self.jpg_data mediafile.save() mediafile = MediaFile(mediafile.path) self.assertIsNotNone(mediafile.art) del mediafile.art mediafile.save() mediafile = MediaFile(mediafile.path) self.assertIsNone(mediafile.art)
def test_delete_partial_date(self): mediafile = self._mediafile_fixture('empty') mediafile.date = datetime.date(2001, 12, 3) mediafile.save() mediafile = MediaFile(mediafile.path) self.assertIsNotNone(mediafile.date) self.assertIsNotNone(mediafile.year) self.assertIsNotNone(mediafile.month) self.assertIsNotNone(mediafile.day) delattr(mediafile, 'month') mediafile.save() mediafile = MediaFile(mediafile.path) self.assertIsNotNone(mediafile.date) self.assertIsNotNone(mediafile.year) self.assertIsNone(mediafile.month) self.assertIsNone(mediafile.day)
def op_reload_md5(mdb, args, mf, dry_run): path = mdb.abspath(mf.relative_path) if not os.path.isfile(path): logging.error("Cannot find file %s." % mf.relative_path) return False new_mf = MediaFile(mf) new_mf.load_file_info(path) if \ new_mf.path == mf.path and \ new_mf.file_size == mf.file_size and \ new_mf.middle_md5 == mf.middle_md5: return False # update file info logging.info("Updating: %s" % mdb.abspath(mf.relative_path)) logging.info("old: %s" % mf) logging.info("new: %s" % new_mf) if dry_run: return False try: mdb.update( mf.id, path=new_mf.path, file_size=new_mf.file_size, middle_md5=new_mf.middle_md5 ) except sqlite3.IntegrityError: conflict_mf = mdb.get(middle_md5=new_mf.middle_md5) logging.error('IntegrityError: middle_md5 conflict with: %s' % conflict_mf) return False return True
def transfer_tags(src: Pathish, dst: Pathish, remove_art: bool = False) -> None: src = Path(src).resolve() dst = Path(dst).resolve() f = MediaFile(src) g = MediaFile(dst) for field in f.fields(): if remove_art and field in ("art", "images"): continue try: setattr(g, field, getattr(f, field)) except: pass g.save()
def test_set_image_structure(self): mediafile = self._mediafile_fixture('empty') image = Image(data=self.png_data, desc=u'album cover', type=ImageType.front) mediafile.images = [image] mediafile.save() mediafile = MediaFile(mediafile.path) self.assertEqual(len(mediafile.images), 1) image = mediafile.images[0] self.assertEqual(image.data, self.png_data) self.assertEqual(image.mime_type, 'image/png') self.assertExtendedImageAttributes(image, desc=u'album cover', type=ImageType.front)
def test_delete_tag(self): mediafile = self._mediafile_fixture('full') keys = self.full_initial_tags.keys() for key in set(keys) - set(['art', 'month', 'day']): self.assertIsNotNone(getattr(mediafile, key)) for key in keys: delattr(mediafile, key) mediafile.save() mediafile = MediaFile(mediafile.filename) for key in keys: value = getattr(mediafile, key) if isinstance(value, list): assert not value else: self.assertIsNone(value)
def test_add_image_structure(self): mediafile = self._mediafile_fixture('image') self.assertEqual(len(mediafile.images), 2) image = Image(data=self.png_data, desc=u'the composer', type=ImageType.composer) mediafile.images += [image] mediafile.save() mediafile = MediaFile(mediafile.filename) self.assertEqual(len(mediafile.images), 3) images = (i for i in mediafile.images if i.desc == u'the composer') image = next(images, None) self.assertExtendedImageAttributes( image, desc=u'the composer', type=ImageType.composer )
def test_add_tiff_image(self): mediafile = self._mediafile_fixture('image') self.assertEqual(len(mediafile.images), 2) image = Image(data=self.tiff_data, desc=u'the composer', type=ImageType.composer) mediafile.images += [image] mediafile.save() mediafile = MediaFile(mediafile.filename) self.assertEqual(len(mediafile.images), 3) # WMA does not preserve the order, so we have to work around this image = list(filter(lambda i: i.mime_type == 'image/tiff', mediafile.images))[0] self.assertExtendedImageAttributes( image, desc=u'the composer', type=ImageType.composer)
def test_whitelist_and_blacklist(self): item = self.add_item_fixture(year=2016) item.write() mf = MediaFile(syspath(item.path)) self.assertEqual(mf.year, 2016) item_id = item.id self.config['zero']['fields'] = [u'year'] self.config['zero']['keep_fields'] = [u'comments'] self.load_plugins('zero') with control_stdin('y'): self.run_command('zero') item = self.lib.get_item(item_id) self.assertEqual(item['year'], 2016) self.assertEqual(mf.year, 2016)
def test_write_counters_without_total(self): mediafile = self._mediafile_fixture('full') self.assertEqual(mediafile.track, 2) self.assertEqual(mediafile.tracktotal, 3) self.assertEqual(mediafile.disc, 4) self.assertEqual(mediafile.disctotal, 5) mediafile.track = 10 delattr(mediafile, 'tracktotal') mediafile.disc = 10 delattr(mediafile, 'disctotal') mediafile.save() mediafile = MediaFile(mediafile.path) self.assertEqual(mediafile.track, 10) self.assertEqual(mediafile.tracktotal, None) self.assertEqual(mediafile.disc, 10) self.assertEqual(mediafile.disctotal, None)
def _set_pattern(self, field): """Populate `self.fields_to_progs` for a given field. Do some sanity checks then compile the regexes. """ if field not in MediaFile.fields(): self._log.error(u'invalid field: {0}', field) elif field in ('id', 'path', 'album_id'): self._log.warning( u'field \'{0}\' ignored, zeroing ' u'it would be dangerous', field) else: try: for pattern in self.config[field].as_str_seq(): prog = re.compile(pattern, re.IGNORECASE) self.fields_to_progs.setdefault(field, []).append(prog) except confuse.NotFoundError: # Matches everything self.fields_to_progs[field] = []
def get_cover(metaDict): cover = None cover = Image.open(script_path + '/images/default-cover-v6.jpg') covers = [ 'Cover.jpg', 'cover.jpg', 'Cover.jpeg', 'cover.jpeg', 'Cover.png', 'cover.png', 'Cover.tif', 'cover.tif', 'Cover.tiff', 'cover.tiff', 'Folder.jpg', 'folder.jpg', 'Folder.jpeg', 'folder.jpeg', 'Folder.png', 'folder.png', 'Folder.tif', 'folder.tif', 'Folder.tiff', 'folder.tiff' ] if metaDict['source'] == 'radio': if 'coverurl' in metaDict: rc = '/var/local/www/' + metaDict['coverurl'] if path.exists(rc): if rc != '/var/local/www/images/default-cover-v6.svg': cover = Image.open(rc) elif metaDict['source'] == 'airplay': cover = ap_back elif metaDict['source'] == 'bluetooth': cover = bt_back elif metaDict['source'] == 'input': cover = jp_back elif metaDict['source'] == 'spotify': cover = sp_back elif metaDict['source'] == 'squeeze': cover = sq_back else: if 'file' in metaDict: if len(metaDict['file']) > 0: fp = '/var/lib/mpd/music/' + metaDict['file'] mf = MediaFile(fp) if mf.art: cover = Image.open(BytesIO(mf.art)) return cover else: for it in covers: cp = os.path.dirname(fp) + '/' + it if path.exists(cp): cover = Image.open(cp) return cover return cover
def create_importer(self, item_count=1, album_count=1): """Create files to import and return corresponding session. Copies the specified number of files to a subdirectory of `self.temp_dir` and creates a `ImportSessionFixture` for this path. """ import_dir = os.path.join(self.temp_dir, b'import') if not os.path.isdir(import_dir): os.mkdir(import_dir) album_no = 0 while album_count: album = util.bytestring_path(f'album {album_no}') album_dir = os.path.join(import_dir, album) if os.path.exists(album_dir): album_no += 1 continue os.mkdir(album_dir) album_count -= 1 track_no = 0 album_item_count = item_count while album_item_count: title = f'track {track_no}' src = os.path.join(_common.RSRC, b'full.mp3') title_file = util.bytestring_path(f'{title}.mp3') dest = os.path.join(album_dir, title_file) if os.path.exists(dest): track_no += 1 continue album_item_count -= 1 shutil.copy(src, dest) mediafile = MediaFile(dest) mediafile.update({ 'artist': 'artist', 'albumartist': 'album artist', 'title': title, 'album': album, 'mb_albumid': None, 'mb_trackid': None, }) mediafile.save() config['import']['quiet'] = True config['import']['autotag'] = False config['import']['resume'] = False return ImportSessionFixture(self.lib, loghandler=None, query=None, paths=[import_dir])
def test_cli_writes_only_r128_tags(self): if self.backend == "command": # opus not supported by command backend return album = self.add_album_fixture(2, ext="opus") for item in album.items(): self._reset_replaygain(item) self.run_command(u'replaygain', u'-a') for item in album.items(): mediafile = MediaFile(item.path) # does not write REPLAYGAIN_* tags self.assertIsNone(mediafile.rg_track_gain) self.assertIsNone(mediafile.rg_album_gain) # writes R128_* tags self.assertIsNotNone(mediafile.r128_track_gain) self.assertIsNotNone(mediafile.r128_album_gain)
def test_subcommand_query_exclude(self): item = self.add_item_fixture(year=2016, day=13, month=3, comments=u'test comment') item.write() self.config['zero']['fields'] = ['comments'] self.config['zero']['update_database'] = False self.config['zero']['auto'] = False self.load_plugins('zero') self.run_command('zero', 'year: 0000') mf = MediaFile(syspath(item.path)) self.assertEqual(mf.year, 2016) self.assertEqual(mf.comments, u'test comment')
def test_write_date_components(self): mediafile = self._mediafile_fixture('full') mediafile.year = 2001 mediafile.month = 1 mediafile.day = 2 mediafile.original_year = 1999 mediafile.original_month = 12 mediafile.original_day = 30 mediafile.save() mediafile = MediaFile(mediafile.path) self.assertEqual(mediafile.year, 2001) self.assertEqual(mediafile.month, 1) self.assertEqual(mediafile.day, 2) self.assertEqual(mediafile.date, datetime.date(2001, 1, 2)) self.assertEqual(mediafile.original_year, 1999) self.assertEqual(mediafile.original_month, 12) self.assertEqual(mediafile.original_day, 30) self.assertEqual(mediafile.original_date, datetime.date(1999, 12, 30))
def test_no_patterns(self): self.config['zero']['fields'] = ['comments', 'month'] item = self.add_item_fixture( comments=u'test comment', title=u'Title', month=1, year=2000, ) item.write() self.load_plugins('zero') item.write() mf = MediaFile(syspath(item.path)) self.assertIsNone(mf.comments) self.assertIsNone(mf.month) self.assertEqual(mf.title, u'Title') self.assertEqual(mf.year, 2000)
def test_empty_query_n_response_no_changes(self): item = self.add_item_fixture(year=2016, day=13, month=3, comments=u'test comment') item.write() item_id = item.id self.config['zero']['fields'] = ['comments'] self.config['zero']['update_database'] = True self.config['zero']['auto'] = False self.load_plugins('zero') with control_stdin('n'): self.run_command('zero') mf = MediaFile(syspath(item.path)) item = self.lib.get_item(item_id) self.assertEqual(item['year'], 2016) self.assertEqual(mf.year, 2016) self.assertEqual(mf.comments, u'test comment') self.assertEqual(item['comments'], u'test comment')
def __init__(self): super(ZeroPlugin, self).__init__() self.register_listener('write', self.write_event) self.register_listener('import_task_choice', self.import_task_choice_event) self.config.add({ 'auto': True, 'fields': [], 'keep_fields': [], 'update_database': False, }) self.fields_to_progs = {} self.warned = False """Read the bulk of the config into `self.fields_to_progs`. After construction, `fields_to_progs` contains all the fields that should be zeroed as keys and maps each of those to a list of compiled regexes (progs) as values. A field is zeroed if its value matches one of the associated progs. If progs is empty, then the associated field is always zeroed. """ if self.config['fields'] and self.config['keep_fields']: self._log.warning( u'cannot blacklist and whitelist at the same time') # Blacklist mode. elif self.config['fields']: for field in self.config['fields'].as_str_seq(): self._set_pattern(field) # Whitelist mode. elif self.config['keep_fields']: for field in MediaFile.fields(): if (field not in self.config['keep_fields'].as_str_seq() and # These fields should always be preserved. field not in ('id', 'path', 'album_id')): self._set_pattern(field)
def test_subcommand_update_database_true(self): item = self.add_item_fixture( year=2016, day=13, month=3, comments='test comment' ) item.write() item_id = item.id self.config['zero']['fields'] = ['comments'] self.config['zero']['update_database'] = True self.config['zero']['auto'] = False self.load_plugins('zero') with control_stdin('y'): self.run_command('zero') mf = MediaFile(syspath(item.path)) item = self.lib.get_item(item_id) self.assertEqual(item['year'], 2016) self.assertEqual(mf.year, 2016) self.assertEqual(mf.comments, None) self.assertEqual(item['comments'], '')
def test_convert_an_audio_file(testfile_tree): """qop can copy a file""" root, src_dir, dst_dir = testfile_tree src = src_dir.joinpath("sine.flac") dst = dst_dir.joinpath("sine.mp3") # expected destination name _utils_tests.make_dummy_flac(src) f = MediaFile(src) f.artist = "foobar" f.save() subprocess.run([ "python3", QOP, "-v", "--log-file", "/dev/null", "convert", src, dst_dir ], cwd=root) wait_for_queue() assert src.exists() assert dst.exists() assert MediaFile(dst).artist == f.artist
def test_overwrite_property(self): with self.assertRaises(ValueError) as cm: MediaFile.add_field('artist', MediaField()) self.assertIn(u'property "artist" already exists', unicode(cm.exception))
def test_properties_from_readable_fields(self): path = os.path.join(_common.RSRC, b'full.mp3') mediafile = MediaFile(path) for field in MediaFile.readable_fields(): self.assertTrue(hasattr(mediafile, field))
def test_known_fields(self): fields = list(ReadWriteTestBase.tag_fields) fields.extend(('encoder', 'images', 'genres', 'albumtype')) assertCountEqual(self, MediaFile.fields(), fields)
def test_fields_in_readable_fields(self): readable = MediaFile.readable_fields() for field in MediaFile.fields(): self.assertIn(field, readable)
def cover_art(): @after_this_request def add_header(resp): if 'X-Sendfile' in resp.headers: app.logger.debug('Using X-Sendfile or X-Accel-Redirect') app.logger.debug(resp.headers['X-Sendfile']) resp.headers['X-Accel-Redirect'] = resp.headers['X-Sendfile'] return resp # retrieve folder from database status, res = get_entity(request, Folder) if not status: return res # Check the folder id given for jpgs app.logger.debug('Cover Art Check: ' + res.path + '/*.jp*g') coverfile = os.listdir(res.path) coverfile = fnmatch.filter(coverfile, '*.jp*g') # when there is not a jpeg in the folder check files for embedded art if not coverfile: app.logger.debug('No Art Found in Folder, Checking Files!') for tr in res.tracks: app.logger.debug('Checking ' + tr.path + ' For Artwork') try: mf = MediaFile(tr.path) coverfile = getattr(mf, 'art') if coverfile is not None: if type(coverfile) is list: coverfile = coverfile[0] coverfile = StringIO(coverfile) app.logger.debug('Serving embedded cover art') break except: app.logger.debug('Problem reading embedded art') return request.error_formatter(70, 'Cover art not found'), 404 return request.error_formatter(70, 'Cover art not found'), 404 else: app.logger.debug('Found Images: ' + str(coverfile)) coverfile = coverfile[0] coverfile = os.path.join(res.path, coverfile) app.logger.debug('Serving cover art: ' + coverfile) size = request.args.get('size') if size: try: size = int(size) except: return request.error_formatter(0, 'Invalid size value'), 500 else: size = 1000 im = Image.open(coverfile) size_path = os.path.join(config.get('base', 'cache_dir'), str(size)) path = os.path.join(size_path, str(res.id)) if not os.path.exists(size_path): os.makedirs(size_path) if size > im.size[0] and size > im.size[1]: app.logger.debug('Not resizing Image, adding to cache') im.save(path, 'JPEG') return send_file(path) app.logger.debug('Saving resized image to: ' + path) if os.path.exists(path): app.logger.debug('Serving cover art: ' + path) return send_file(path) im.thumbnail([size, size], Image.ANTIALIAS) im.save(path, 'JPEG') app.logger.debug('Serving cover art: ' + path) return send_file(path)
def analyse(target_level): self.config['replaygain']['targetlevel'] = target_level self._reset_replaygain(item) self.run_command(u'replaygain', '-f') mediafile = MediaFile(item.path) return mediafile.rg_track_gain
def write_tags(filename, tags): f1 = MediaFile(filename) writeTags = "y" showMoreOptions = "n" date = tags["release_date"].split("-") if not "-A" in OPTIONS: writeTags = input("\nWrite tags? (y/n): ") if writeTags == "y": print("\nWriting tags...") # Deletes current tags from the song f1.delete() date = tags["release_date"].split("-") f1.title = tags["title"] f1.album = tags["album_title"] # f1.artist = tags["artists"] f1.day = date[0] f1.month = date[1] f1.year = date[2] # f1.track = tags["track_number"] # f1.tracktotal = tags["total_tracks"] # f1.disc = f"{tags["disc_number"]} # f1.disctotal = tags["total_discs"] f1.genre = tags["genre"] f1.albumartist = tags["album_artist"] # Drops "Album Artist" Tag f1.__dict__["mgfile"].pop("album artist") file_dir = os.path.dirname(filename) if (file_dir != ""): os.chdir(file_dir) if not "-p" in OPTIONS: f1.art = get_artwork(filename, (tags["album_title"], tags["album_artist"])) f1.save() f2 = FLAC(filename) f2["Artist"] = tags["artists"] f2["tracknumber"] = [f"{tags['track_number']}"] f2["discnumber"] = [f"{tags['disc_number']}"] f2.save() print("Tags written successfully!") filename_ext = os.path.splitext(filename)[1] title = f1.title + " - " + f1.albumartist + filename_ext if not os.path.isfile(title): os.rename(filename, title) if os.path.isfile("./cover.jpg"): os.remove("./cover.jpg") if len(OUTPUT) != 0: dest = os.path.join(OUTPUT[0], os.path.basename(filename)) if os.path.exists(dest): os.remove(dest) if os.path.exists(filename): shutil.move(filename, OUTPUT[0]) elif os.path.exists(title): shutil.move(title, OUTPUT[0]) if writeTags == "n" and not "-A" in OPTIONS: showMoreOptions = input("Show more options? (y/n): ") return showMoreOptions
def __init__(self, file): self.path = file self.item = MediaFile(self.path)
def _open_file(file: io.BufferedReader) -> MediaFile: start_position = file.tell() in_file = MediaFile(file) file.seek(start_position) return in_file
def tagger(conf, destination, releaseid, source): _log = init_logging(conf) if not destination: destination = source cfg = TaggerConfig(source, destination, conf) if cfg.id_tag in cfg.release_tags: releaseid = cfg.release_tags[cfg.id_tag].strip() if releaseid: release_id = releaseid if not releaseid: click.echo('Please specify the discogs.com releaseid ("-r")') sys.exit(1) _log.info('Attempting to tag files from target destination={0}'.format(destination)) discogs_release = DiscogsAlbum(DiscogsWrapper().discogs, release_id, cfg.split_artists, cfg.split_genres_and_styles) release = TaggerUtils(discogs_release, cfg) # ensure we were able to map the release appropriately. if not release.tag_map: _log.fatal("Unable to map available audio files to the number of tracks in the Discogs release '{0}'. Exiting".format( release_id)) sys.exit(1) artist = cfg.split_artists.join(release.album.artists) artist = release.album.clean_name(artist) _log.info("Tagging album '{0} - {1}'".format(artist, release.album.title)) dest_dir_name = release.dest_dir_name if os.path.exists(dest_dir_name): _log.fatal('Destination directory already exists. directory={0}. Aborting operation'.format(dest_dir_name)) sys.exit(1) else: _log.info("Creating destination directory '{0}'".format(dest_dir_name)) mkdir_p(dest_dir_name) _log.info("Downloading and storing images") release.album.get_images(dest_dir_name, cfg.images_format, cfg.first_image_name) disc_names = dict() folder_names = dict() if release.album.disctotal > 1 and cfg.split_discs_folder: _log.debug("Creating disc structure") for i in range(1, release.album.disctotal + 1): folder_name = "%s%.d" % (release.album_folder_name, i) disc_dir_name = os.path.join(dest_dir_name, folder_name) mkdir_p(disc_dir_name) # This is duplicate, remove one of the following statements disc_names[i] = disc_dir_name folder_names[i] = folder_name else: folder_names[1] = "" for track in release.tag_map: # copy old file into new location if release.album.disctotal > 1 and cfg.split_discs_folder: target_folder = disc_names[int(track['discnumber'])] else: target_folder = dest_dir_name _log.debug("Source file {0}".format(os.path.join(source, track['orig_file']))) _log.info("Writing file {0}".format(os.path.join(target_folder, track['new_file']))) _log.debug("metadata -> {0:2d} {1} - {2}".format(track['tracknumber'], track['artist'], track['title'])) _log.debug("----------> {0}".format(track['new_file'])) shutil.copyfile(track['orig_file'], os.path.join(target_folder, track['new_file'])) # load metadata information metadata = MediaFile(os.path.join(target_folder, track['new_file'])) # read already existing (and still wanted) properties keep_tags = {} if cfg.keep_tags: for name in cfg.keep_tags.split(","): try: getattr(metadata, name) except AttributeError: _log.warn('Unable to keep_tag. tag={0}'.format(name)) continue keep_tags[name] = getattr(metadata, name) # remove current metadata metadata.delete() # set album metadata metadata.album = release.album.title if cfg.split_discs_folder and release.album.disctotal > 1: # the fileext should be stored on the album/track as well fileext = os.path.splitext(track['orig_file'])[1] disc_title_extension = release._value_from_tag_format(cfg.split_discs_extension, track['tracknumber'], track['position'] - 1, fileext) metadata.album = "{0}{1}".format(metadata.album, disc_title_extension) metadata.composer = artist metadata.albumartist = artist metadata.albumartist_sort = release.album.sort_artist metadata.label = release.album.label metadata.year = release.album.year metadata.country = release.album.country metadata.url = release.album.url # add styles to the grouping tag (right now, we can just use one) metadata.grouping = release.album.styles # adding two as there is no standard. discogstagger pre v1 # used (TXXX desc="Catalog #") # mediafile uses TXXX desc="CATALOGNUMBER" metadata.catalognum = release.album.catno metadata.catalognumber = release.album.catno # use the correct genre field, on config use the first style genre = release.album.genres if cfg.use_style: genre = release.album.style metadata.genre = genre metadata.discogs_id = release_id if release.album.disctotal and release.album.disctotal > 1 and track['discnumber']: _log.debug("writing disctotal and discnumber") metadata.disc = track['discnumber'] metadata.disctotal = release.album.disctotal if release.album.is_compilation: metadata.comp = True metadata.comments = release.album.note # encoder if cfg.encoder_tag is not None: metadata.encoder = cfg.encoder_tag # if track.discsubtotal: # metadata.discsubtotal = track.discsubtotal # set track metadata metadata.title = track['title'] metadata.artist = track['artist'] metadata.artist_sort = track['sortartist'] metadata.track = track['tracknumber'] # the following value will be wrong, if the disc has a name or is a multi # disc release --> fix it metadata.tracktotal = release.album.tracktotal_on_disc(track['discnumber']) # it does not make sense to store this in the "common" configuration, but only in the # id.txt. we use a special naming convention --> most probably we should reuse the # configuration parser for this one as well, no? for name, value in list(cfg.release_tags.items()): if name.startswith("tag:"): name = name.split(":") name = name[1] setattr(metadata, name, value) first_image_name = cfg.first_image_name # this should be done in a cleaner way to avoid multiple images in different # folders (use the dest_dir again....) if cfg.embed_coverart and os.path.exists(os.path.join(dest_dir_name, first_image_name)): imgdata = open(os.path.join(dest_dir_name, first_image_name), 'rb').read() imgtype = imghdr.what(None, imgdata) if imgtype in ("jpeg", "png"): _log.debug("Embedding album art.") metadata.art = imgdata if keep_tags is not None: for name in keep_tags: setattr(metadata, name, keep_tags[name]) metadata.save() # start supplementary actions if cfg.write_nfo: _log.info("Generating .nfo file") release.create_nfo() # adopt for multi disc support if cfg.write_m3u: _log.info("Generating .m3u file") release.create_m3u(folder_names) # copy "other files" on request if cfg.copy_other_files and len(release.copy_files) > 0: _log.info("copying files from source directory") copy_files = release.copy_files dir_list = os.listdir(source) _log.debug("start_dir: {0}".format(source)) _log.debug("dir list: {0}".format(dir_list)) file_list = [os.path.join(source, x) for x in dir_list if not x.lower().endswith(TaggerUtils.FILE_TYPE) and os.path.isfile(os.path.join(source, x))] copy_files.extend(file_list) for fname in copy_files: if not fname.endswith(".m3u"): _log.debug("source: {0}".format(fname)) _log.debug("target: {0}".format(os.path.join(dest_dir_name, os.path.basename(fname)))) shutil.copyfile(fname, os.path.join(dest_dir_name, os.path.basename(fname))) # remove source directory, if configured as such. if not cfg.keep_original: _log.info("Deleting source directory '{0}'".format(source)) shutil.rmtree(source) _log.info("Tagging complete.")
def test_write_initial_key_tag(self): self.modify(u"initial_key=C#m") item = self.lib.items().get() mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.initial_key, u'C#m')
def test_write_custom_tags(self): item = self.add_item_fixture(artist='old artist') item.write(tags={'artist': 'new artist'}) self.assertNotEqual(item.artist, 'new artist') self.assertEqual(MediaFile(syspath(item.path)).artist, 'new artist')
def test_invalid_descriptor(self): with self.assertRaises(ValueError) as cm: MediaFile.add_field('somekey', True) self.assertIn(u'must be an instance of MediaField', unicode(cm.exception))