Peters Flexible RenAmiNg Kit (PFrank) Forum Index Peters Flexible RenAmiNg Kit (PFrank)
Support and Discussion Site for the PFrank File/Folder Renaming Tool (http://www3.telus.net/pfrank)
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Flexible Date Formatter

 
Post new topic   Reply to topic    Peters Flexible RenAmiNg Kit (PFrank) Forum Index -> Plugins
View previous topic :: View next topic  
Author Message
nharding



Joined: 19 Nov 2007
Posts: 11

PostPosted: Sun Nov 25, 2007 3:58 am    Post subject: Flexible Date Formatter Reply with quote

There doesn't seem to be anyway of doing an attachment, so I've got a cut down version of PfrankUser.py below in the code section.

I tested it with a variety of date formats from files I downloaded from the net. It is VERY flexible on recognising dates, all the following dates are handled correctly (as well as many more).

"Date 2nd July 1967 test",
"Date July-2-1967 test",
"Date Jul 1967 test",
"september-5-43",
"sep 1943",
"5 sept 43",
"Date 17-12-2007 test",
"(1967-07-02) # What the end result should be",
"171207",
"1943 # Not a valid date",
"1943 until 1945-11 # Not a valid date, followed by valid one",
"198507 #YYYYMM",
"July 1st 1961 to 2nd July 1967 # Multiple dates",

You can change the output format by selecting the View \ Options \ Date Formatter. I have added a few small extensions, the month can be a season, or a two month span. So the following are valid dates.

"Christmas 2001",
"Fall 2000",
"March-April 1999",

On outputting the dates if you use month names then the extended forms are used, so format string of %Y %b for the last item in the list above would give 1999 Mar-Apr, and %B %y would give March-April 99. For the extended form of months there is no day field. The extended months have default numeric value associated with them so Christmas 2001 would be 2001-12, Fall 2000 gives 2000-09 and March-April 1999 gives 1999-03 if you are using a numeric format.

Sometimes the day is not available and so there is an extension in the output, and you can use ~ to only display that if day is present. So using an output of Y%-%m~-%d with an input of July 2 1967 would give 1967-07-02, but for an input of July 1967 it would give 1967-07.



Code:

#!/usr/bin/python

PFrankUserTemplateVersion = 0.2

##########################################
# list your imported modules here.
# If you get import errors, then the modules are not
# present in the environment.  In this case you will have to
# insert the required module in the PFrank install folder.
##########################################

# start of user imported modules
import re
import string
import datetime
# end of user imported modules.


##########################################
# The following modules must always be imported
##########################################

# start of required imported modules
try :
    from SearchRep_init import configurator
    from SearchRepBase import SearchRepBase
    from SearchRepConstants import *
except :
    from SearchRep_initStubs import configurator
    from SearchRepBaseStubs import SearchRepBase

# end of required imported modules

class DateRenamer (SearchRepBase) :
  """ This is a date renamer class.  The SearchRepLower base class is
  mandatory.
  """

  def __init__ (self) :
     
  # call base class initializer.  This is mandatory
    SearchRepBase.__init__(self)

    # This is the ID string that will appear in the pre-defined command
    # pull down list.  It will also appear in the custom list when
    # inserted.  The id will also be used in the scan summary
    # The name 'self.idstring' must not change.  Set the assigned string
    # on the right-hand side of the assignment statement to whatever
    # name you want.
    self.idstring = "Convert dates using date formatter"

    # This regular expression is "weak", it will let some non dates in
    # this is fine, because we do "strong" checks in code
   
    self.date = re.compile(r"""
        (?i)^(.*?)
        (\d\dst|\d\dnd|\d\drd|\d\dth|\d\d|\dst|\dnd|\drd|\dth|
        Jan[-uary. ]+Feb[ruary]*|Feb[-ruary. ]+Mar[ch]*|
        Mar[-ch. ]+Apr[il]*|Apr[-il. ]+May|May[-. ]+Jun[e]*|
        Jun[-e. ]+Jul[y]*|Jul[-y. ]+Aug[ust]*|
        Aug[-ust. ]+Sep[tember]*|Sep[-tember. ]+Oct[ober]*|
        Oct[-ober. ]+Nov[ember]*|Nov[-ember. ]+Dec[ember]*|
        Dec[-ember. ]+Jan[uary]*|
        Jan[uary]*|Feb[ruary]*|Mar[ch]*|Apr[il]*|May|Jun[e]*|
        Jul[y]*|Aug[ust]*|Sep[tember]*|Oct[ober]*|Nov[ember]*|
        Dec[ember]*|Spring[-. ]*Special*|Easter[-. ]*Special|
        Summer[-. ]*Special|Fall[-. ]*Special|Autumn[-. ]*Special|
        Winter[-. ]*Special|Christmas[-. ]*Special|
        X[-. ]*mas[-. ]*Special|Holiday[-. ]*Special|Spr[ing]*|Eas[ter]*|
        Sum[mer]*|Fall|Aut[-mn]*|Win[ter]*|Christmas|X[-. ]*mas|\d)
        ([-., ]*)
        (\d\dst|\d\dnd|\d\drd|\d\dth|\d\d|\dst|\dnd|\drd|\dth|
        Jan[-uary. ]+Feb[ruary]*|Feb[-ruary. ]+Mar[ch]*|
        Mar[-ch. ]+Apr[il]*|Apr[-il. ]+May|May[-. ]+Jun[e]*|
        Jun[-e. ]+Jul[y]*|Jul[-y. ]+Aug[ust]*|
        Aug[-ust. ]+Sep[tember]*|Sep[-tember. ]+Oct[ober]*|
        Oct[-ober. ]+Nov[ember]*|Nov[-ember. ]+Dec[ember]*|
        Dec[-ember. ]+Jan[uary]*|
        Jan[uary]*|Feb[ruary]*|Mar[ch]*|Apr[il]*|May|Jun[e]*|
        Jul[y]*|Aug[ust]*|Sep[tember]*|Oct[ober]*|Nov[ember]*|
        Dec[ember]*|Spring[-. ]*Special*|Easter[-. ]*Special|
        Summer[-. ]*Special|Fall[-. ]*Special|Autumn[-. ]*Special|
        Winter[-. ]*Special|Christmas[-. ]*Special|
        X[-. ]*mas[-. ]*Special|Holiday[-. ]*Special|Spr[ing]*|Eas[ter]*|
        Sum[mer]*|Fall|Aut[-mn]*|Win[ter]*|Christmas|X[-. ]*mas|\d)
        ([-., ]*)
        (\d\dst|\d\dnd|\d\drd|\d\dth|\d\d|\dst|\dnd|\drd|\dth|
        Jan[-uary. ]+Feb[ruary]*|Feb[-ruary. ]+Mar[ch]*|
        Mar[-ch. ]+Apr[il]*|Apr[-il. ]+May|May[-. ]+Jun[e]*|
        Jun[-e. ]+Jul[y]*|Jul[-y. ]+Aug[ust]*|
        Aug[-ust. ]+Sep[tember]*|Sep[-tember. ]+Oct[ober]*|
        Oct[-ober. ]+Nov[ember]*|Nov[-ember. ]+Dec[ember]*|
        Dec[-ember. ]+Jan[uary]*|
        Jan[uary]*|Feb[ruary]*|Mar[ch]*|Apr[il]*|May|Jun[e]*|
        Jul[y]*|Aug[ust]*|Sep[tember]*|Oct[ober]*|Nov[ember]*|
        Dec[ember]*|Spring[-. ]*Special*|Easter[-. ]*Special|
        Summer[-. ]*Special|Fall[-. ]*Special|Autumn[-. ]*Special|
        Winter[-. ]*Special|Christmas[-. ]*Special|
        X[-. ]*mas[-. ]*Special|Holiday[-. ]*Special|Spr[ing]*|Eas[ter]*|
        Sum[mer]*|Fall|Aut[-mn]*|Win[ter]*|Christmas|X[-. ]*mas|\d)
        ([-., ]*)
        (\d\dst|\d\dnd|\d\drd|\d\dth|\d\d|\dst|\dnd|\drd|\dth|
        Jan[-uary. ]+Feb[ruary]*|Feb[-ruary. ]+Mar[ch]*|
        Mar[-ch. ]+Apr[il]*|Apr[-il. ]+May|May[-. ]+Jun[e]*|
        Jun[-e. ]+Jul[y]*|Jul[-y. ]+Aug[ust]*|
        Aug[-ust. ]+Sep[tember]*|Sep[-tember. ]+Oct[ober]*|
        Oct[-ober. ]+Nov[ember]*|Nov[-ember. ]+Dec[ember]*|
        Dec[-ember. ]+Jan[uary]*|
        Jan[uary]*|Feb[ruary]*|Mar[ch]*|Apr[il]*|May|Jun[e]*|
        Jul[y]*|Aug[ust]*|Sep[tember]*|Oct[ober]*|Nov[ember]*|
        Dec[ember]*|Spring[-. ]*Special*|Easter[-. ]*Special|
        Summer[-. ]*Special|Fall[-. ]*Special|Autumn[-. ]*Special|
        Winter[-. ]*Special|Christmas[-. ]*Special|
        X[-. ]*mas[-. ]*Special|Holiday[-. ]*Special|Spr[ing]*|Eas[ter]*|
        Sum[mer]*|Fall|Aut[-mn]*|Win[ter]*|Chr[istmas]*|X[-. ]*mas|\d)?
        ($|[^0-9]+.*)$    # look for six or 8 digit number in middle of string
        # if ends with p, then it is page count and not date
        """, re.VERBOSE)

    self.number = re.compile(r"(\d\d\d\d|\d\d|\d).*")
    self.invalidSeperator = re.compile(r"\w.*")
    self.ordinal = re.compile(r"(.*[stndrdth]+.*)")
    self.prefixEnd = re.compile(r"[a-zA-Z#]")

    self.months = [
        re.compile(r"(?i)^Jan[uary]*$"),
        re.compile(r"(?i)^Feb[ruary]*$"),
        re.compile(r"(?i)^Mar[ch]*$"),
        re.compile(r"(?i)^Apr[il]*$"),
        re.compile(r"(?i)^May$"),
        re.compile(r"(?i)^Jun[e]*$"),
        re.compile(r"(?i)^Jul[y]*$"),
        re.compile(r"(?i)^Aug[ust]*$"),
        re.compile(r"(?i)^Sep[tember]*$"),
        re.compile(r"(?i)^Oct[ober]*$"),
        re.compile(r"(?i)^Nov[ember]*$"),
        re.compile(r"(?i)^Dec[ember]*$"),
        re.compile(r"(?i)^Jan[-uary. ]+Feb[ruary]*$"),
        re.compile(r"(?i)^Feb[-ruary. ]+Mar[ch]*$"),
        re.compile(r"(?i)^Mar[-ch. ]+Apr[il]*$"),
        re.compile(r"(?i)^Apr[-il. ]+May$"),
        re.compile(r"(?i)^May[-. ]+Jun$"),
        re.compile(r"(?i)^Jun[-e. ]+Jul[y]*$"),
        re.compile(r"(?i)^Jul[-y. ]+Aug[ust]*$"),
        re.compile(r"(?i)^Aug[-ust. ]+Sep[tember]*$"),
        re.compile(r"(?i)^Sep[-tember. ]+Oct[ober]*$"),
        re.compile(r"(?i)^Oct[-ober. ]+Nov[ember]*$"),
        re.compile(r"(?i)^Nov[-ember. ]+Dec[ember]*$"),
        re.compile(r"(?i)^Dec[-ember. ]+Jan[uary]*$"),
        re.compile(r"(?i)^Spr[ing]*$"),
        re.compile(r"(?i)^Eas[ter]*$"),
        re.compile(r"(?i)^Sum[mer]*$"),
        re.compile(r"(?i)^Fall$|Aut[umn]*$"),
        re.compile(r"(?i)^Win[ter]*$"),
        re.compile(r"(?i)^Chr[istmas-]*$|X[-]*mas$"),
        re.compile(r"(?i)^Spring[-. ]*Special$"),
        re.compile(r"(?i)^Easter[-. ]*Special$"),
        re.compile(r"(?i)^Summer[-. ]*Special$"),
        re.compile(r"(?i)^Fall[-. ]*Special$|Autumn[-. ]Special$"),
        re.compile(r"(?i)^Winter[-. ]*Special$"),
        re.compile(r"(?i)^Christmas[-. ]*Special$|X[-]*mas[-. ]Special$"),
        re.compile(r"(?i)^Holiday[-. ]*Special$"),
        ]

    self.monthValues = [
        0,1,2,3,4,5,6,7,8,9,10,11,
        0,1,2,3,4,5,6,7,8,9,10,11,
        2,3,6,8,10,11,
        2,3,6,8,10,11,
        ]

    self.monthNamesShort = [
        "Jan","Feb","Mar","Apr","May","Jun",
        "Jul","Aug","Sep","Oct","Nov","Dec",
        "Jan-Feb","Feb-Mar","Mar-Apr","Apr-May","May-Jun","Jun-Jul",
        "Jul-Aug","Aug-Sep","Sep-Oct","Oct-Nov","Nov-Dec","Dec-Jan",
        "Spring","Easter","Summer","Fall","Winter","Xmas",
        "Spring Special","Easter Special","Summer Special",
        "Fall Special","Winter Special","Xmas Special","Holiday Special"
        ]
   
    self.monthNames = [
        "January","February","March","April","May","June",
        "July","August","September","October","November","December",
        "January-February","February-March","March-April",
        "April-May","May-June","June-July","July-August",
        "August-September","September-October","October-November",
        "November-December","December-January",
        "Spring","Easter","Summer","Fall","Winter","Christmas",
        "Spring Special","Easter Special","Summer Special",
        "Fall Special","Winter Special","Christmas Special",
        "Holiday Special"
        ]

    self.dayNamesShort = [
        "Mon","Tue","Wed","Thu","Fri","Sat","Sun"
        ]

    self.dayNames = [
        "Monday","Tuesday","Wednesday","Thursday",
        "Friday","Saturday","Sunday"
        ]

    self.standardFormatFullYear = re.compile(r"YYYY")
    self.standardFormatYear = re.compile(r"YY")
    self.standardFormatMonth = re.compile(r"MM")
    self.standardFormatDay = re.compile(r"DD")

# I have extended custom format, ? means ignore next field IF day is not defined
    self.customFormatRemove = re.compile(r"~[-. ]*[%]?.")
    self.customFormatClean = re.compile(r"~")
    self.customFormatEscape = re.compile(r"%%")
    self.customFormatWeekday = re.compile(r"%a")
    self.customFormatFullWeekday = re.compile(r"%A")
    self.customFormatRemoveExtendedMonth = re.compile(r"[- .]*%[bB]x")
    self.customFormatExtendedMonthNamesShort = re.compile(r"%bx")
    self.customFormatMonthNamesShort = re.compile(r"%b")
    self.customFormatExtendedMonthNames = re.compile(r"%Bx")
    self.customFormatMonthNames = re.compile(r"%B")
    self.customFormatDay = re.compile(r"%d")
    self.customFormatMonth = re.compile(r"%m")
    self.customFormatYear = re.compile(r"%y")
    self.customFormatFullYear = re.compile(r"%Y")
    self.customFormatWeek = re.compile(r"%W")           
   
  def initforscan(self, VerificationTest=False) :
        """
        This function is called whenever a new scan or rescan is made.  Use it to
        reset anything that needs to be reinitialized before a scan.
        This function is mandatory.
        """
        pass

  def getInt(self,val) :
        """
        This returns val as int or -1, if it isn't valid
        It allows for suffix, so 2nd, gives 2
        """
        num = self.number.findall(val)
        if num == [] :
            return -1
        return int (num[0])

  def getMonthDay(self,month,day) :
        """
        Return month and day, if month > 12 then it must be day
        """

        if month > 12 :
            return day-1,month
        else :
            return month-1,day

  def ZeroPadded(self,num) :
        """
        Return 08 rather than 8
        """

        if num < 0 :
            return "01"
       
        if num < 10 :
            return "0" + str(num)
        else :
            return str(num)
       
       
  def reformatDate(self,day,month,year) :
    """
    Format date according to rename rules
    For now just use (YYYY-MM-DD)
    """

    dayStr = self.ZeroPadded(day)
    monthStr = self.ZeroPadded(self.monthValues[month]+1)
    yearStr = self.ZeroPadded(year % 100)
    fullYearStr = str(year)

    if useCustomDate :
        currDay = day
        if day <= 0 :
            currDay = 1

        useDate = datetime.date(year,self.monthValues[month]+1,currDay)
        ignoreYear, week, dow = useDate.isocalendar()

        newDate = self.customFormatEscape.sub("%",customDateFormat)
       
        if day <0> 11:
            newDate = self.customFormatExtendedMonthNamesShort.sub(self.monthNamesShort[month],newDate)
        else :
            newDate = self.customFormatRemoveExtendedMonth.sub("",newDate)

        newDate = self.customFormatMonthNamesShort.sub(self.monthNamesShort[month],newDate)

        if month > 11:
            newDate = self.customFormatExtendedMonthNames.sub(self.monthNames[month],newDate)

        newDate = self.customFormatMonthNames.sub(self.monthNames[month],newDate)
        newDate = self.customFormatDay.sub(dayStr,newDate)
        newDate = self.customFormatMonth.sub(monthStr,newDate)
        newDate = self.customFormatYear.sub(yearStr,newDate)
        newDate = self.customFormatFullYear.sub(fullYearStr,newDate)
        newDate = self.customFormatWeek.sub(self.ZeroPadded(week),newDate)
    else :
        newDate = self.standardFormatFullYear.sub(fullYearStr,standardDateFormat)
        newDate = self.standardFormatYear.sub(yearStr,newDate)
        newDate = self.standardFormatDay.sub(dayStr,newDate)
        newDate = self.standardFormatMonth.sub(monthStr,newDate)
        newDate = self.standardFormatMonth.sub(monthStr,newDate)

    return newDate

   
  def checkIfMonth(self,month) :
    """
    Gets index for the month
    Input:  string to check to see if it is a month (or season)
    Output: index of the month (0-11,or season), -1 if not found
    """

    if self.number.match(month) != None :
        return -1
   
   
    for curr in range(len(self.months)) :
        if self.months[curr].match(month) :
            return curr
    return -1

  def fixnames(self, filename,VerificationTest=False) :
    try :
        return self.doFixnames(filename,VerificationTest)
    except:
        print "<Error> in DateRenamer :",filename
        return False, filename
   
  def doFixnames(self, filename,VerificationTest=False) :
    """
    This function converts name of file to a new name.
    Input:  string representing the old filename or portion (either All, Prefix, or Extension)
            The name does not include the path to the file.
    Output: change indicator
            True if change to input string occurred, otherwise False
            string representing the new filename

   
    When the old filename string is passed into this routine, then depending
    on where this user command is placed in the custom list, the string could
    be in the middle of a transformation. 

    e.g. if the original filename was ABCDEF.jpg, and the first command of the
    custom list inserted a counter in front of the name, and the second command
    was this user command, then the filename string that is passed in could be
    something like 0010-ABCDEF.jpg.
    This name of course no longer looks like the original name.
   
    If you needed to extract meta data from the file, then you would not be able to
    use the passed in string.  Therefore the global variable 'configurator.filename' is
    provided which has the full path to the filename.  You can then just open that name,
    extract the meta data, and then close the file.
    """

# full path to original filename
    fullPathForFile = configurator.filename

#########################################################################
# Insert code to modify the filename here
#########################################################################

    day = 0
    year = -1
    month = -1
    skip = False
    append2nd = False
    newname = filename
    groups = self.date.findall(filename)
    eightDigit = False
       
    if groups != [] :

        prefix = groups[0][0]
        postfix = groups[0][8]
        arg1 = groups[0][1]
        sep1 = groups[0][2]
        arg2 = groups[0][3]
        sep2 = groups[0][4]
        arg3 = groups[0][5]
        sep3 = groups[0][6]
        arg4 = groups[0][7]

        if postfix == filename :
            return False, filename

        if self.invalidSeperator.match(postfix) != None :
            if (arg4 == '') & (sep3 == '') :
                postfix = arg3 + sep3 + arg4 + postfix
                arg3 = ''
            else :
                postfix = arg4 + postfix
                arg4 = ''

        if self.prefixEnd.match(prefix[-1:]) != None:
            if (len(arg1) == 2) & (len(arg2) == 2) & (len(arg3) == 2) & (len(arg4) == 2) & (sep1 == '') & (sep2 == '') & (sep3 == '') :
                eightDigit = True
            else :
                prefix = prefix + arg1 + sep1
                arg1 = ''
                sep1 = ''

# Ok, it is potential date to get past regular expression
# [0] group is prepender, it used only on replacement
# [1-7] groups are either YY,MM,DD or seperators
# First we want to find the month (for named months & seasons)
        month = self.checkIfMonth(arg1)
        #if it starts with month, next is either, year or day
        if month >= 0 :
            day = self.getInt (arg2)
            # if day is more than 31, it must be a year
            if day > 31 :
                year = 1900 + day
                day = 0
            # if group 4 is [] then there is no seperator between
            # digits and it is year, unless day is ordinal (1st,2nd,3rd, etc)
            if (sep2 == '') & (self.ordinal.match(arg2) == None) :
                year = day * 100 + int (arg3)
                day = 0
            else :
                year = int (arg3)
                if arg4 != '' :
                    year = year * 100 + int (arg4)
                elif year <20>= 0:
                   
                if (sep2 != sep1) & (self.ordinal.match(arg1) == None) :
                    append2nd = True
                else :
                    day = self.getInt (arg1)
                year = int (arg3)

                if arg4 != '' :
                    year = year * 100 + int (arg4)
                elif year < 20 :
                    year = 2000 + year
                else :
                    year = 1900 + year
            else :
                #It's either numeric, or YYYY Month
                #OR not valid

                if (len(sep1) > 0 ) & (len(sep2) > 0) & (sep1 != sep2) :
                    skip = True

                if (eightDigit == False) & (self.prefixEnd.match(prefix[-1:]) != None) :
                    skip = True

                if skip == False :
                    first = self.getInt(arg1)
                    second = self.getInt(arg2)
                    third = self.getInt(arg3)
                    fourth = self.getInt(arg4)
                   
                    month = self.checkIfMonth(arg3)

                if month >= 0 :
                    skip = True
                    if (second > 31) | ((first == 20) & (second < 10)) :
                        year = first * 100 + second
                        day = fourth
                    else :
                        day = first
                        if second <10> 11) & (day > 0) :
                        month = -1
                        skip = False

                #it must be numeric format then, lets do sanity tests
                #1943 for example can appear as valid

                if (len(arg2) == 1) & (sep2 == '') :
                    skip = True
#                if (sep1 == '') & (sep2 == '-') & (sep3 == '') :
#                    skip = True
                if (len(arg2) == 1) | (len(arg3) == 1) | (len(arg4) == 1) :
                    skip = True

                if skip == False :

                    if first > 31 :
                        #Ok, we have YYMMDD, or YYDDMM, assume YYMMDD
                        #unless month is >= 12
                        year = 1900 + first
                        month , day = self.getMonthDay(second,third)

                    #if month <0>= 19) & (first <20> 31 :
                                    year = 1900 + first
                                    month , day = self.getMonthDay(second,third)
                                elif third > 31 :
                                    year = 1900 + third
                                    month , day = self.getMonthDay(first,second)
                                elif (second > 31) | ((second <10> 12
                        if month > 12 :
                            month = -1
               
            #Process all the other rules

        ignore, tailend = self.fixnames(postfix)

        #if we have a valid month, then assume date is valid
       
        if month >= 0 :
            if arg4 == '' :
                tailend = sep3 + tailend
            if append2nd :
                newname = prefix + arg1 + sep1 + self.reformatDate(day,month,year) + tailend
            else :
                newname = prefix + self.reformatDate(day,month,year) + tailend
        else :
            newname = prefix + arg1 + sep1 + arg2 + sep2 + arg3 + sep3 + arg4 + tailend
                       

    #########################################################################
    # these statements are mandatory
    #########################################################################
    change = False
    if filename != newname :
        change = True

    return change, newname
# end of the class definition for DateRenamer


###################################################################
# Create the Renamer Objects in a list.  The list is mandatory. 
# The name of the list must not change.
# You can list as many names in the list as you like.  PFrank will try to
# load all of them.  Each name in the list must correspond to the
# name of a user command renaming class.  A name can only appear
# once in the list.
#
# User Command Objects are created with the following syntax:
#     ClassName()
#       i.e. the name of the class followed by ()
###################################################################
UserRenamerList = [
    DateRenamer(),    # format date as YYYY-MM-DD
    ]

if  __name__ != '__main__' :
    standardDateFormat = configurator.optionlist[SEARCHREP_OPTIONDATEFORMAT_ID]
    customDateFormat = configurator.optionlist[SEARCHREP_OPTIONCUSTOMDATE_ID]
    useCustomDate = configurator.optionlist[SEARCHREP_CUSTOMORFIXEDDATE_ID] == "Custom Format"

######################################
# Code for testing the renamer objects
######################################
if  __name__ == '__main__' :
  """
  This is some test code to test the renaming objects.  Test the code using
  the python IDLE tool to verify that things work.  Then try importing the file
  to PFrank
  """
  import os

 
  userpath = os.getcwd()
  userpath = os.path.normpath(userpath)

  print "Initializing Local Stubs"

  ###################################################################
  # Stubs for Local Testing.  These are in addition to the
  # stubs imported earlier.

  standardDateFormat = "YYYYMMDD"
  customDateFormat = "(%Y-%m~-%d %Bx)"
  useCustomDate = True
 
  print "Testing User Defined Renaming Classes"

  # this is a table of sample filenames for testing
  # Assume that the files are in the current folder.
  nameTable = [
# Test Date Formating     
      "Date 2nd July 1967 test",
      "Date July-2-1967 test",
      "Date Jul 1967 test",
      "september-5-43",
      "sep 1943",
      "5 sept 43",
      "Date 17-12-2007 test",
      "(1967-07-02) # What the end result should be",
      "171207",
      "1943 # Not a valid date",
      "1943 until 1945-11 # Not a valid date, followed by valid one",
      "198507 #YYYYMM",
      "July 1st 1961 to 2nd July 1967 # Multiple dates",
      "dilbert20060205",
# Now we test padding
# Now we test volume splitting (seperate directories)
# and directories based on Title name     
      ]

  # run all the initializers
  for renamer in UserRenamerList :
      renamer.initforscan()
     
  # run all name fixers
  for renamer in UserRenamerList :
      print "*************Testing Renamer: ", renamer.idstring
      for name in nameTable :
          fullpath = os.path.join(os.getcwd(), name)
          configurator.filename = os.path.normpath(fullpath)

          change, newname = renamer.fixnames(name)
          print  "Oldname is: ", name
          print  "Newname is: ", newname
          assert  (change == (not name == newname))
          print ""

Back to top
View user's profile Send private message
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Mon Nov 26, 2007 7:50 am    Post subject: Reply with quote

I tried loading the PFrankUser.py excerpt that you provided and it doesn't compile due to these lines:

=====================
else :
year = int (arg3)
if arg4 != '' :
year = year * 100 + int (arg4)
elif year <20>= 0:

if (sep2 != sep1) & (self.ordinal.match(arg1) == None) :
append2nd = True
else :
day = self.getInt (arg1)
year = int (arg3)

if arg4 != '' :
year = year * 100 + int (arg4)
elif year < 20 :
year = 2000 + year
else :
year = 1900 + year
else :
=========================

I would like to try out the file. Would you please send me a copy via email.

Thanks,

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
nharding



Joined: 19 Nov 2007
Posts: 11

PostPosted: Sun Dec 02, 2007 1:14 am    Post subject: Reply with quote

Did you get chance to look at my modified file? If you want to modify it, or include it feel free. (You might want to tidy it up though Wink)

And what do you think of my idea of 2 pass renaming, so that you can see all the files to be processed and then come up with a naming scheme for that.
Back to top
View user's profile Send private message
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Sun Dec 02, 2007 8:42 am    Post subject: Reply with quote

I didn't receive any modified file.
Yes - I would like to try it and save it. If other people send me their User files, then I can make those available for all in the future.

Don't know what you mean by the 2 pass renaming. Each row of the custom renaming panel already acts like a renaming pass.

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
nharding



Joined: 19 Nov 2007
Posts: 11

PostPosted: Sun Dec 02, 2007 9:55 pm    Post subject: Reply with quote

I sent another email to you (to the other email address).

When I was talking about 2 pass renaming I was talking about the following.

If I have a selection of files, that when processed give Photo 17, Photo 21, Photo 100, Music 1, Music 10, I would like it to rename them to Photo 017, Photo 021, and Photo 100, Music 01, Music 10. I know how to do a rule to rename n digits to m digits, but I want to write a user command that automatically detects the highest value used for each name, and then pads the other names to match.

Another thing that will use the same code is to automatically move files into subdirectories, so that in the example above it would create Photo and Music directories and move the files into those directories (but only if more than a certain threshold of files was reached).

I also plan on adding something to allow you to automatically prepend then directory name to all the files (and another to move them up in the directory structure). So you could have music\Beetles\Hard Days Night.mp3 and the first command would rename Hard Days Night.mp3 to Beetles - Hard Days Night.mp3, and then the other command would move that file into the music directory.
Back to top
View user's profile Send private message
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Mon Dec 03, 2007 5:37 am    Post subject: Reply with quote

Thanks - I received the email.

If I understand your 2-pass renaming idea correctly I think it is already there. i.e. Each row of the custom renaming list is like a pass of renaming.
For example you can insert your user-defined DateFormatter command into row 1 of the list. You can then insert your upcoming user-defined command which move files to Photo and Music folders into row2. Both of those commands can be coded into the PFrankUser.py file and appear as separate commands in the pre-defined drop-down list.

You could add another command into the PFrankUser.py file to prepend folder names; that command can be inserted into row 3. If you weren't looking for the threshold, you could instead add the existing pre-defined command for inserting folder names into row 3. There is also a pathbuilder option for regular expressions which can be used to move the files into different folders (could insert into row 4).
More rows with predefined ocmmand or regex search/replace could be used to do final tweaking like removing uinwanted characters, removing excess blank characters, fixing capitalizations, etc.

Hope this helps,

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
nharding



Joined: 19 Nov 2007
Posts: 11

PostPosted: Mon Dec 03, 2007 6:13 am    Post subject: Reply with quote

You can almost do what I want. But I want it to find all the titles with numbers in them and decide how many digits are needed for each title individually. You need a 2nd pass to do that. Ie Photos (1967) 1, Photos 10 (1973) , Photos_100. After processing through some rules you get Photos 1 (1967), Photos 10 (1973), Photos 100. I want it to say I need 3 digits for the number so that it would become Photos 001 (1967), Photos 010 (1973), Photos 100. If there were just those three files in the directory, it would also know that it doesn't need to move them to a subdirectory. But if you also had Music 1, Music 2, Music 3 then it would decide to create 2 subdirectories, one called Photos and one called Music, it would move the files into the appropriate subdirectories. I want to make it as automated as possible Smile rather than selecting and deselecting rules (I already have a rule to change 3 digit number to 4 digit number) which I select before running the rules.
Back to top
View user's profile Send private message
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Mon Dec 03, 2007 7:25 am    Post subject: Reply with quote

OK - I see what you are after.
There is already a post-processing flag for a regex row.
Not sure if there is an easy way to add this functionality for user-defined (or predefined) commands. I'll have to think about it.

One alternative is to use 2 renaming lists. Use the first list to do the post-processing which uses a user-defined command to determine how many digits you need and store that info using a variable in PFrankUser.py. Then use the second list to call the remaining commands, the first of which would use the variable to convert numbers to their required number of digits.

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Tue Dec 04, 2007 6:40 am    Post subject: Reply with quote

I've had alook at this and have 2 possible solutions.

1)
I adapted the postprocessing available for regex lines to also be available for pre-defined commands (which includes user-defined commands). I still have to test it and decide on a syntax for pre-defined flags. This will be available sometime in the future. However, this is really meant to do post-processing after all the duplication checking. What you really need is preprocessing.

2)
For preprocessing you can use the already available initforscan function which is defined for all user-defined commands. This is currently called once before the scanning starts. I am going to rearrange the scanner so that this function is called just after obtaining the initial list of names using the name filters. The name list will be made available as a global variable which you can access.
Then in the initforscan for your user-defined dateformatter (or perhaps some new user command), you can prescan all the names and determine how large a number field you will need and how many names would be changed. then the regular processing would commence with all the new information.
Does that sound like it could work for you?
If so, I can have a beta program ready tomorrow.

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
nharding



Joined: 19 Nov 2007
Posts: 11

PostPosted: Tue Dec 04, 2007 4:14 pm    Post subject: Reply with quote

That sounds good thanks, I will be making a new command. I'm already working on another new one that will prepend directory name to the file names (it's a LOT more complex than that though). If you have a directory called Music To Die For\ and files called Music To Die For 1.mp3 MTDF 2.mp3, 3.mp3, then it will rename MTDF 2 and 3.
Back to top
View user's profile Send private message
admin
Site Admin


Joined: 09 Mar 2007
Posts: 446
Location: Canada

PostPosted: Wed Dec 05, 2007 2:49 am    Post subject: Reply with quote

A beta is available at:

http://www3.telus.net/pfrank/PFrankSetup2.111.exe

It has the global scanlist that you can access in your PFrankUser.py file using the initforscan function. The variable is in 'configurator.scanlist'. The example below prints the list:

===================================
def initforscan(self, VerificationTest=False) :
"""
This function is called whenever a new scan or rescan is made. Use it to
reset anything that needs to be reinitialized before a scan.
This function is mandatory.
"""
print "scan list is: ", configurator.scanlist
===================================

This is the list of names that have passed the name filtering. You should be able to process the list to determine how many digits your numbers need, etc.

Let me know if there are any problems

Peter.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Peters Flexible RenAmiNg Kit (PFrank) Forum Index -> Plugins All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © phpBB Group. Hosted by phpBB.BizHat.com


Start Your Own Video Sharing Site

Free Web Hosting | Free Forum Hosting | FlashWebHost.com | Image Hosting | Photo Gallery | FreeMarriage.com

Powered by PhpBBweb.com, setup your forum now!
For Support, visit Forums.BizHat.com