Find and later delete zombie informatica objects - informatica

Is there a easy way to identify and clean unused informatica artifacts?
Context: In one of the projects, there are lot of zombie sessions / mappings etc, the creators have long gone.
I want to do the following:
List/Delete all sessions that are not associated with a workflow.
List/Delete all mappings that are not used in any session/wf.
List/Delete all source/target that were not used in any mapping.
List/Delete all workflows that were not run in the past one year.
Someone mentioned about using : Designer > Tools > Queries . I can't express the above 1/2/3/4 with the option given, can anyone shed some light?
Note:
I’m not looking for click one by one and find dependencies.
I’m not looking for download the whole plant as xml and search dependencies
one by one

As this is not easily achievable with PowerCenter itself, I tried to come up with some simple tool to solve it. For the full description and download link please go to this page.
Below you'll find the code published as requested in comments: Find and later delete zombie informatica objects
Feel free to use, share and improve :) Any code review will be also much appreciated.
import subprocess
import os
from subprocess import *
import platform
import sys
import getpass
import configparser
#global variables declarations
currentDir=''
pmrepPath=''
domainFile=''
def connect_to_repo(Repository,Domain,User,Host,Port, UserSecurityDomain):
#password = raw_input("Enter password for Repository: " + Repository + ", User: " + User)
password = getpass.getpass()
print "\nConnecting..."
if Domain != '':
RepoCommand="pmrep connect -r "+Repository+" -d "+Domain+" -n "+User + " -x " + password #+" -X DOMAIN_PWD"
else:
RepoCommand="pmrep connect -r "+Repository+" -n "+User + " -x " + password + " -h " + Host + " -o " + Port
if UserSecurityDomain != '':
RepoCommand += " -s " + UserSecurityDomain
RepoCommand=RepoCommand.rstrip()
p=subprocess.Popen(RepoCommand,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
out,err=p.communicate()
if p.returncode or err:
print "Connection Failed"
print err.strip()
print out.strip()
sys.stdout.flush()
sys.stdin.flush()
else:
print "Connection Successful"
sys.stdout.flush()
sys.stdin.flush()
return p.returncode
def execute_pmrep_command(command, output_file_name, start_line, end_line, line_prefix):
if len(line_prefix)>0: line_prefix+=' '
out=open(output_file_name,'a')
return_code=subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
output,error=return_code.communicate()
for line in output.split('\r\n')[start_line:end_line]:
out.writelines(line_prefix + line + '\n')
out.close()
return
def check_platform():
global domainFile
global currentDir
global pmrepPath
global platForm
platForm=platform.system()
print "Platform recognized : "+platForm
## if not os.getenv('INFA_HOME', 'C:\\Informatica\\9.5.1'):
## print "INFA_HOME env_variable not set in your "+platForm+" platform."
## print "Please set INFA_HOME and continue."
## raw_input()
## sys.exit(0)
if not os.getenv('INFA_DOMAINS_FILE'):
print "INFA_DOMAINS_FILE env_variable not set in your "+platForm+" platform."
print "Please set INFA_DOMAINS_FILE and continue."
raw_input()
sys.exit(0)
## elif not os.getenv('DOMAIN_PWD', 'vic'):
## print "DOMAIN_PWD env variable not set in your "+platForm+" platform."
## print "Please set DOMAIN_PWD and continue."
## raw_input()
## sys.exit(0)
## else:
## if platForm == 'Windows':
## pmrepPath=os.getenv('INFA_HOME').strip()+"\clients\PowerCenterClient\client\\bin"
## elif platForm == 'Linux':
## pmrepPath=os.getenv('INFA_HOME').strip()+"/server/bin"
## currentDir=os.getcwd()
## domainFile=os.getenv('INFA_DOMAINS_FILE','C:\\Informatica\\9.5.1\\domains.infa').strip()
config = configparser.RawConfigParser()
config.optionxform = lambda option: option
config.read('InfaRepo_ListUnusedObjects.cfg')
infaDir = config.get('Common', 'infaDir').strip()
Repository = config.get('Common', 'Repository').strip()
Domain = config.get('Common', 'Domain').strip()
Host = config.get('Common', 'Host').strip()
Port = config.get('Common', 'Port').strip()
Folder = config.get('Common', 'Folder').strip()
User = config.get('Common', 'User').strip()
UserSecurityDomain = config.get('Common', 'UserSecurityDomain').strip()
objectTypeList = config.get('Common', 'objectTypeList').split(',')
if Domain != '':
print 'Domain provided, will be used to connect.'
else:
print 'Domain not provided, Host and Port will be used to connect.'
for i in range(len(objectTypeList)):
objectTypeList[i]=objectTypeList[i].strip()
currentDir=os.getcwd()
outputDir=currentDir+'\\UnusedObjectsReport'
###objectTypeList = ['mapplet', 'mapping', 'session', 'source', 'target', 'worklet']
##
##objectTypeList = ['target']
pmrepPath=infaDir.strip()+"\clients\PowerCenterClient\client\\bin"
os.chdir(pmrepPath)
outFile = outputDir + "\ListOfUnusedObjects.txt"
if not os.path.exists(os.path.dirname(outFile)):
os.makedirs(os.path.dirname(outFile))
print 'Output file: ' + outFile
open(outFile,'w').writelines("Domain : "+Domain+"\nRepository : "+Repository+"\nUserName : "+User+"\n")
open(outFile,'a').writelines("***************************"+"\n")
open(outFile,'a').writelines("LIST OF UNUSED OBJECTS:\n")
outBatchFile = outputDir + "\DeleteUnusedObjects.bat"
tempDir = outputDir + "\\temp"
if not os.path.exists(outputDir):
os.makedirs(outputDir)
if not os.path.exists(tempDir):
os.makedirs(tempDir)
for tempFile in os.listdir(tempDir):
os.remove(os.path.join(tempDir, tempFile))
print 'Output batch file: ' + outBatchFile
if Domain != '':
RepoCommand="pmrep connect -r "+Repository+" -d "+Domain+" -n "+User
else:
RepoCommand="pmrep connect -r "+Repository+" -n "+User + " -h " + Host + " -o " + Port
if UserSecurityDomain != '':
RepoCommand += " -s " + UserSecurityDomain
open(outBatchFile,'w').writelines(pmrepPath+"\\"+RepoCommand+"\n")
objectTypeCounter=0
return_code=connect_to_repo(Repository,Domain,User,Host,Port,UserSecurityDomain)
objDepDict={}
error = False
errorList = []
#check if repository connection is successfull
if return_code==0:
for objectType in objectTypeList:
objectTypeCounter+=1
print "Step {0} of {1}: {2}".format(objectTypeCounter, len(objectTypeList), objectType)
objectFile = tempDir + "\\" + objectType + ".txt"
open(objectFile,'w').writelines("")
objectDepFile = tempDir + "\\" + objectType + "_dep.txt"
open(objectDepFile,'w').writelines("")
execute_pmrep_command("pmrep listobjects -f " + Folder + " -o " + objectType, objectFile, 8, -4, '')
objectList=open(objectFile).readlines()
objectCounter=0
if len(objectList) == 0:
print '\tNo {0}s found'.format(objectType)
elif objectList[0][:3] == ' [[':
error=True
for line in objectList:
errorList += [line.replace('\n','')]
break
for line in objectList:
objectCounter+=1
fields=line.split(' ')
if len(fields) == 2:
objectType=fields[0]
objectName=fields[1][:-1]
else:
objectType=fields[0]
objectName=fields[2][:-1]
#if the object is non-reusable, it obviously is in some workflow, so skipp it
if fields[1] == 'non-reusable':
print "\t{0} {1} of {2}: {3} is not a reusable {4} - skipping".format(objectType, objectCounter, len(objectList), objectName, objectType)
continue
command = "pmrep listobjectdependencies -f " + Folder + " -n " + objectName + " -o " + objectType + " -p parents"
#print "Getting object dependencies for " + objectType + " " + objectName
print "\t{0} {1} of {2}: {3}".format(objectType, objectCounter, len(objectList), objectName)
execute_pmrep_command(command, objectDepFile, 8, -6, objectName)
#find unused objects
for fileLine in open(objectDepFile,'r').readlines():
line = fileLine.split(' ')
if len(line) == 3:
Name = line[0]
ParentType = line[1]
ParentName = line[2]
else:
Name = line[0]
ParentType = line[1]
ParentName = line[3]
try:
objDepDict[objectType + ': ' + Name]+=[ParentType + ' ' + ParentName]
except:
objDepDict[objectType + ': ' + Name]=[ParentType + ' ' + ParentName]
found = False
for objectKey in objDepDict.iterkeys():
objectType, objName = objectKey.replace(' ','').split(':')
if len(objDepDict[objectKey]) <= 1:
if not found:
print '\n'
print 'Following unused objects have been found:'
found = True
print '\t{0}: {1}'.format(objectType, objName)
open(outFile,'a').writelines('{0}: {1}\n'.format(objectType, objName))
open(outBatchFile,'a').writelines("rem {0}\\pmrep deleteobject -f {1} -o {2} -n {3}\n".format(pmrepPath, Folder, objectType, objName))
execute_pmrep_command('pmrep cleanup', 'log.txt', 0, 0, '')
open(outBatchFile,'a').writelines(pmrepPath+'\\pmrep cleanup' + '\n')
if not error:
if not found:
print 'No unused objects found.'
print '\nDone.'
print 'Output file: ' + outFile
print 'Output batch file: ' + outBatchFile
else:
print 'Following errors occured:'
for e in errorList:
print '\t', e
#wait for key press
print '\nHit Enter to quit...'
raw_input()
#End of program

Related

UTF-8 to EBCDIC using iconv in Python-script on USS

I am trying to convert utf-8 files from a directory listing on USS into ebcdic files BEFORE getting them into z/OS datasets.
Using a helper function which I found on stackoverflow (thanks for this!) I can issue shell-commands from within the python script:
def r(cmd_line):
return Popen(cmd_line.split(), stdout=PIPE).communicate()[0]
With this I can allocate and populate mainframe datasets from USS-files, using
r("tso alloc DSNAME(...) etc.") # to allocate a mainframe DS and
r("tso oget ...") # to populate the mainframe DS
However: some files need to be converted first, which in a shellscript I would simply code with
iconv -f UTF-8 -t IBM-1141 $utf8_file > $ebcdic_file
and I am totally at a loss of how to do this in python (2.7)?
Can't ask anybody in my shop since python was newly installed and I am currently the only one interested in it. Anyone an idea? Thanks a lot in advance!
Although not in the true spirit of python, you can do what you want by wrapping USS commands in a python script. Here is an example:
#!/bin/env python
from cStringIO import StringIO
import os
import sys
def r(cmd):
import subprocess
return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
def allocate_dataset(dsName):
name = "'" + dsName + "'"
out = r(['/bin/tso', 'alloc', 'ds(' + name + ')', 'space(6000 2000)', 'track', 'lrecl(80)',
'dsntype(library)', 'blksize(3200)', 'recfm(f b)', 'dir(2)', 'new'])
for line in out.split():
print line
def not_allocated(dsName):
name = "'" + dsName + "'"
out = r(['/bin/tsocmd', 'listds ' + name])
for line in out.split():
if "NOT IN CATALOG" in out:
return True
return False
def ascii_to_ebcdic(from_codepage, to_codepage, fileName):
os.system('iconv -f' + from_codepage + ' -t' + to_codepage + ' <' + fileName + ' >ebcdic_' + fileName)
def copy_to_dataset(fileName, dsName, memberName):
dsn = "//'" + dsName + '(' + memberName + ")'"
os.system('cp -T ' + fileName + ' "' + dsn + '"')
def main():
dsName = "HLQ.MY.PYTHON"
if not_allocated(dsName):
print("Allocating '" + dsName + "' data set")
allocate_dataset(dsName)
ascii_to_ebcdic("UTF-8", "IBM-1047", "test.txt")
copy_to_dataset("ebcdic_test.txt", "HLQ.MY.PYTHON", "TXT")
member = "//'HLQ.MY.PYTHON(TXT)'"
os.system('cat -v "' + member + '"')
main()

Create Documentation using Doxygen and non-Doxygen commented source code

We got here some like 10 years old C and C++ code, without documents or manual. However the source is documented in the header files quite good, but it is a lot of working going through all the files looking for an information. It looks like this:
// Description description ....
//
// #param parameter 1 name:
// description of parameter 1
//
// #param parameter 2 name:
// description of parameter 2
//
Returntype Functionname(parameter1, parameter2);
Using doxygen wizard a documentation can be created but all the comments are lost, because they are not formated in a way the parser understands.
So is that a format i dont know? Can i teach the parser what to do? Or is it a special format that is used by another software?
I wrote a python script, to convert the comments to a format the parser understands. It's not pretty, it's not safe, but it works for us.
import re
import time
import os
import shutil
def convertHeaderDocumentation(file):
with open(file) as f:
lines = f.readlines()
lines = [line.rstrip('\n') for line in lines]
scanning = False
commentLines = []
convertedDocument = ""
declaration = ""
for line in lines:
if line == "" or \
line.strip().startswith("#"):
if len(commentLines) > 0:
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear()
convertedDocument += line + "\n"
continue
if line.strip().startswith('//'):
if not scanning:
commentLines.clear()
scanning = True
commentLines.append(line)
else:
if scanning:
if line.strip() != "":
declaration = line.strip()
match = re.search('\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*;', declaration)
if not match is None:
# check for function description
description = ""
for line in commentLines:
if line[2:].strip().startswith("#") or \
line[2:].strip() == "":
break
else:
description += line[2:].strip()
# scan for parameter description
parameters = []
parameter = ""
scanning = False
for line in commentLines:
# start scanning, if line starts with #
if line[2:].strip().startswith("#") and \
scanning == False :
# if present add to parameter lst
if parameter != "":
parameters.append(parameter)
scanning = True
parameter = line[2:].strip() + " "
continue
# stop scanning if an empty line is read
if line[2:].strip() == "":
scanning = False
# save if parameter is in buffer
if parameter != "":
parameters.append(parameter)
parameter = ""
if scanning == True and line[2:].strip() != "":
parameter += line[2:].strip()
convertedDocument += "/**\n"
convertedDocument += " * #fn " + declaration[:-1] + "\n"
convertedDocument += " *\n"
convertedDocument += " * #brief "
restLine = 80 - len(" * #brief ")
for index in range(0, len(description), restLine):
convertedDocument += description[index:index + restLine] + "\n * "
convertedDocument += "\n"
for parameter in parameters:
convertedDocument += " * " + parameter + "\n *\n"
convertedDocument += " * #return " + match.group(1) + "\n"
convertedDocument += " *\n"
convertedDocument += " * #date " + time.strftime("%d.%m.%Y") + "<br> parsed using python\n"
convertedDocument += " */\n"
convertedDocument += declaration + "\n\n"
commentLines.clear()
else :
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear();
return convertedDocument
projectDir = "path to source files goes here"
projectDir = os.abspath(projectDir)
parentProjectDir, projectDirName = os.path.split(projectDir)
convertedDir = os.path.join(parentProjectDir, "converted")
print(convertedDir)
for root, dirs, files in os.walk(projectDir):
# create directory structure if not present
tmpConvertedDir = os.path.join(convertedDir, root[len(projectDir) + 1:])
if not os.path.exists(tmpConvertedDir):
os.makedirs(tmpConvertedDir)
for file in files:
filename, fileextension = os.path.splitext(file)
# only copy/convert c++/c source files
if fileextension in {'.h','.c','.cpp'} :
newPath = os.path.join(tmpConvertedDir, file)
print(newPath)
# convert header files
if fileextension in {'.h'}:
#print("convert ", os.path.join(root, file), " to ", newPath)
converted = convertHeaderDocumentation(os.path.join(root, file))
with open(newPath, 'w') as f:
f.write(converted)
# copy source files
else:
print("copy ", os.path.join(root, file), " to ", newPath)
shutil.copyfile(os.path.join(root, file), newPath)
The function declaration was a bit tricky to catch with regex. For my case
\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*; works just fine, but without any extra keywords a lazy quantifier is going to be more acurate for keywords before the returntype \s*\w*?\s*(\w+)\s+(\w+).*\((.*)[^)].*;
All C and C++ files in a given projectDir directory and subfolders are converted if they are header files or just copy if they are source files. Therefore a directory ..\converted is created which contains the copied/converted files.
With the resulting files doxygen wizard created a sufficient documentation. Maybe this is going to help someone :-)

how to do lowercase of 'xl cell value + some content/somethng '?

here my function . I have to do lower what ever coming in newfilename..i.e newfilename.lower()
def my_function(start, end):
sheetname = 'my-sheet'
filepath = "/myxl.xlsx"
try:
work_book=xlrd.open_workbook(filepath)
except:
print 'error'
try:
worksheet = work_book.sheet_by_name(sheetname)
except:
print 'error'
rows=worksheet.nrows
cols=worksheet.ncols
success = []
fail = []
for row in xrange(start,end):
print "row no. : ",row
state = '/home/myfolder/'
if os.path.exists(state):
print "state folder exits"
else:
os.makedirs(state)
district = state + worksheet.cell_value(row,0) + '/'
if os.path.exists(district):
print "district folder exits"
else:
os.makedirs(district)
city = district + worksheet.cell_value(row,2) + '/'
if os.path.exists(city):
print "city folder exits"
else:
os.makedirs(city)
newfilename = city + worksheet.cell_value(row,4).replace (" ", "-") + '.png'
if worksheet.cell_value(row,5) !="":
oldfilename = worksheet.cell_value(row,5)
else:
oldfilename="no-image"
newfullpath = newfilename
oldfullpath = '/home/old/folder/' + oldfilename
try:
os.rename(oldfullpath,newfullpath)
success.append(row)
except Exception as e:
fail.append(row)
print "Error",e
print 'renaming done for row #' ,row , ' file ', oldfilename , ' to ', newfilename
print 'SUCCESS ', success
print 'FAIL ', fail
newfilename.lower() not working
here when I am going to use unicode error coming...
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 72: ordinal not in range(128)

Trying to edit a txt file from a range of user inputs in python

me: I am very new to coding.
What i'm trying to do: Allow the user to change a txt files data. E.g. The name of a person, the email of a person, etc.
Problem: Code accepts my inputs however, it does not change the txt file.
Code i've made already.
click here for code
L = open("players.txt","r+")
edit_name = raw_input ("Enter the name of the person you wish to edit: ")
for line in L:
s = line.strip()
strings = s.split(",")
if edit_name == strings[0]:
print strings[:8]
print " \t 1 - Forename \n"
print " \t 2 - Surname \n"
print " \t 3 - Email Address \n"
print " \t 4 - Phone Number \n"
print " \t 5 - Division \n"
print " \t 6 - Points in the new division\n"
print " \t 7 - Old division\n"
print " \t 8 - Old points\n"
option = raw_input("Enter the number of what you would like to edit: ")
if option == "1":
updated_forename = raw_input ("New forename: ")
strings[0] = updated_forename
elif option == "2":
updated_surname = raw_input ("New surname: ")
strings[1] = updated_surname
elif option == "3":
updated_email = raw_input("New email: ")
strings[2] = updated_email
elif option == "4":
updated_phone_number = raw_input("New phonenumber: ")
strings[3] = updated_phone_number
elif option == "5":
updated_division = raw_input("New division: ")
strings[4] = updated_division
elif option == "6":
updated_points_new_div = raw_input("New points in division: ")
strings[5] = updated_points_new_div
elif option == "7":
updated_olddivision = raw_input("Old divison: ")
strings[6] = updated_olddivision
elif option == "8":
updated_oldpoints = raw_input("Old Points: ")
strings[7] = updated_oldpoints
print "Updated information"
print strings[:8]
L.close() #Closes the file to free us usage space.
Text file i'm wanting to edit.
click here for text file
Im guessing I need to basically save over the existing text file with the new data that has been entered. The question is how?
Any help would be appreciated.
p.s. First time posting so i cannot post pictures as i don't have 10 reputation. My apologies.
You are never actully writing to the file:
https://docs.python.org/2/tutorial/inputoutput.html
Change "L.open" to write mode "w", use "L.write()" to write new data, this means you need to rewrite the data you don't want to change and construct and write new data where you wanted it to be modified.
Pseudo-code:
Open file
for line in file
if(line.name == selectedname):
write_row_edited(something)
else:
write_line_unedited()
close file
I took the time to insert the missing peudo-code
#we need to load file into memory, so we can edit it (rewrite it modified)
file = open("players.txt","r")
data = file.read()
file.close()
datalines = data.split("\n")
#now we have the file "line-by-line" in memory so we can edit it
edit_name = raw_input ("Enter the name of the person you wish to edit: ")
file = open("players.txt","w")
for line in datalines:
s = line.strip()
strings = s.split(",")
if edit_name == strings[0]:
print strings[:8]
print " \t 1 - Forename \n"
print " \t 2 - Surname \n"
print " \t 3 - Email Address \n"
print " \t 4 - Phone Number \n"
print " \t 5 - Division \n"
print " \t 6 - Points in the new division\n"
print " \t 7 - Old division\n"
print " \t 8 - Old points\n"
option = raw_input("Enter the number of what you would like to edit: ")
if option == "1":
updated_forename = raw_input ("New forename: ")
strings[0] = updated_forename
elif option == "2":
updated_surname = raw_input ("New surname: ")
strings[1] = updated_surname
elif option == "3":
updated_email = raw_input("New email: ")
strings[2] = updated_email
elif option == "4":
updated_phone_number = raw_input("New phonenumber: ")
strings[3] = updated_phone_number
elif option == "5":
updated_division = raw_input("New division: ")
strings[4] = updated_division
elif option == "6":
updated_points_new_div = raw_input("New points in division: ")
strings[5] = updated_points_new_div
elif option == "7":
updated_olddivision = raw_input("Old divison: ")
strings[6] = updated_olddivision
elif option == "8":
updated_oldpoints = raw_input("Old Points: ")
strings[7] = updated_oldpoints
print "Updated information"
print strings[:8]
#merge string so we can write it back
newline = ",".join(strings)
file.write(newline+"\n")
else:
file.write(line+"\n")
file.close()

django make log that works for all models

I am trying to make my own log that makes a string of changed data between object (my old object and my new object) However i keep getting back empty string,
My code:
def log_fields(old_obj, new_obj):
fields = new_obj.__class__._meta.fields
changed_fields = ""
old_data = ""
new_data = ""
# get all changed data
for field in fields:
old_field_data = old_obj.__getattribute__(field.name)
new_field_data = new_obj.__getattribute__(field.name)
if old_field_data != new_field_data:
count =+ 1
# convert changed data to strings
# number + space + data + 5 spaces for next string
changed_fields.join(str(count)).join(" ").join(str(field)).join(" ")
old_data.join(str(count)).join(" ").join(str(old_field_data)).join(" ")
new_data.join(str(count)).join(" ").join(str(new_field_data)).join(" ")
print changed_fields
print old_data
print new_data
I got a feeling something with the string .join combination something is going wrong, cause trying this manually in shell seems to work up to the comparison. Not sure tho hos i should change the string
changed_fields = changed_fields + str(count) + "." + str(field.name) + " "
old_data = old_data + str(count) + "." + str(old_field_data) + " "
new_data = new_data + str(count) + "." + str(new_field_data) + " "
Seems to do the job, so for now, ill keep it at this