<commit_before>#!/usr/bin/env python
from __future__ import print_function
import rb
import rhythmdb
import gtk
import sys
import os

if sys.version_info.major > 2:
	from urllib.parse import unquote as unquote_url
else:
	from urllib import unquote as unquote_url

def super_rename(src, dst):
	"""Move the file at src to dst. If any of dst's parent directories don't
	exist, create them. Recursively prune blank parent directories of src."""

	src_dir = os.path.split(src)[0]
	dst_dir = os.path.split(dst)[0]

	try:
		os.makedirs(dst_dir)
	except OSError as err:
		if err.strerror is 'File exists':
			raise

	os.rename(src, dst)

	try:
		os.removedirs(src_dir)
	except OSError as err:
		pass

class _RDBEntry(object):
	"""Our attributes are RhythmDB information."""

	def __init__(self, rdb, song):
		self.rdb = rdb
		self.song = song

	def __getattr__(self, prop):
		p = getattr(rhythmdb, "PROP_"+prop.upper())
		return self.rdb.entry_get(self.song, p)

class _EscapedRDBEntry(_RDBEntry):
	def __getattr__(self, prop):
		res = _RDBEntry.__getattr__(self, prop)
		if type(res) is str:
			return res.replace('/', '_')
		else:
			return res

class FileOrganizer(rb.Plugin):
	def activate(self, shell):
		"""This is called when we're activated or RhythmBox starts."""

		print("activating...")

		self.new_path = "{0.artist}/{0.album}/{0.track_number} - {0.title}.mp3"
		self.shell = shell
		self.rdb = shell.get_property("db")
		self.uim = shell.get_ui_manager()

		self.add_organize_tool()

	def add_organize_tool(self):
		"""Add an 'Organize Files' entry to the 'Tools' menu associated with
		self.organize()."""

		action = gtk.Action(
			"OrganizeFiles",
			"Organize Files",
			"Rename files on the basis of their metadata.",
			"OrganizeFiles"
		)
		action.connect('activate', self.organize, self.shell)

		action_group = gtk.ActionGroup('OrganizeFilesActionGroup')
		action_group.add_action(action)
		self.uim.insert_action_group(action_group)

		self.uim.add_ui_from_file( self.find_file("file_organizer.xml") )

	def deactivate(self, shell):
		"""This is called when we're deactivated or RhythmBox exits."""

		print("deactivating")

		del self.shell, self.rdb, self.uim

	def organize(self, *_): # The arguments that go into _ are useless.
		"""Rename all the music in our database based on its metadata."""

		self.rdb.entry_foreach(lambda e: self.organize_single_entry(e))

	def organize_single_entry(self, entry):
		"""We're needed because RhythmDB doesn't support the iteration
		protocol."""

		s = _EscapedRDBEntry(self.rdb, entry)

		uri = entry.get_playback_uri()

		if not uri:
			print("WTF?! We got something with a blank URI. Ignoring...")
			return
		elif not uri.startswith("file://"):
			print("ignoring %s" % uri)
			return

		src = unquote_url( uri.partition("://")[2] )
		dst = os.path.join(rb.music_dir(), self.new_path.format(s))

		print("%s -> %s" % (src, dst))
<commit_msg>Don't overwrite files from super_rename().<commit_after>#!/usr/bin/env python
from __future__ import print_function
import rb
import rhythmdb
import gtk
import sys
import os

if sys.version_info.major > 2:
	from urllib.parse import unquote as unquote_url
else:
	from urllib import unquote as unquote_url

def super_rename(src, dst, force=False):
	"""Move the file at src to dst. If any of dst's parent directories don't
	exist, create them. Recursively prune blank parent directories of src."""

	if not force and os.path.exists(dst):
		print("%s already exists. Not renaming." % dst)
		return

	src_dir = os.path.split(src)[0]
	dst_dir = os.path.split(dst)[0]

	try:
		os.makedirs(dst_dir)
	except OSError as err:
		if err.strerror is 'File exists':
			raise

	os.rename(src, dst)

	try:
		os.removedirs(src_dir)
	except OSError as err:
		pass

class _RDBEntry(object):
	"""Our attributes are RhythmDB information."""

	def __init__(self, rdb, song):
		self.rdb = rdb
		self.song = song

	def __getattr__(self, prop):
		p = getattr(rhythmdb, "PROP_"+prop.upper())
		return self.rdb.entry_get(self.song, p)

class _EscapedRDBEntry(_RDBEntry):
	def __getattr__(self, prop):
		res = _RDBEntry.__getattr__(self, prop)
		if type(res) is str:
			return res.replace('/', '_')
		else:
			return res

class FileOrganizer(rb.Plugin):
	def activate(self, shell):
		"""This is called when we're activated or RhythmBox starts."""

		print("activating...")

		self.new_path = "{0.artist}/{0.album}/{0.track_number} - {0.title}.mp3"
		self.shell = shell
		self.rdb = shell.get_property("db")
		self.uim = shell.get_ui_manager()

		self.add_organize_tool()

	def add_organize_tool(self):
		"""Add an 'Organize Files' entry to the 'Tools' menu associated with
		self.organize()."""

		action = gtk.Action(
			"OrganizeFiles",
			"Organize Files",
			"Rename files on the basis of their metadata.",
			"OrganizeFiles"
		)
		action.connect('activate', self.organize, self.shell)

		action_group = gtk.ActionGroup('OrganizeFilesActionGroup')
		action_group.add_action(action)
		self.uim.insert_action_group(action_group)

		self.uim.add_ui_from_file( self.find_file("file_organizer.xml") )

	def deactivate(self, shell):
		"""This is called when we're deactivated or RhythmBox exits."""

		print("deactivating")

		del self.shell, self.rdb, self.uim

	def organize(self, *_): # The arguments that go into _ are useless.
		"""Rename all the music in our database based on its metadata."""

		self.rdb.entry_foreach(lambda e: self.organize_single_entry(e))

	def organize_single_entry(self, entry):
		"""We're needed because RhythmDB doesn't support the iteration
		protocol."""

		s = _EscapedRDBEntry(self.rdb, entry)

		uri = entry.get_playback_uri()

		if not uri:
			print("WTF?! We got something with a blank URI. Ignoring...")
			return
		elif not uri.startswith("file://"):
			print("ignoring %s" % uri)
			return

		src = unquote_url( uri.partition("://")[2] )
		dst = os.path.join(rb.music_dir(), self.new_path.format(s))

		print("%s -> %s" % (src, dst))

{'fraction_non_alphanumeric': 0.13094637754244412, 'fraction_numerical': 0.0030257186081694403, 'mean_word_length': 4.21015761821366, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5477485', 'n_tokens_mistral': 2292, 'n_tokens_neox': 2071, 'n_words': 565}