I am making a renaming script, but I am getting in a bit of trouble with my
Seach and Replace function.
Actually, the function works as long as there are no duplication of the same
object in the hierarchy. For example, as depicted in the attachment, locator1
and locator2 are created from scratch, whereas locator3 is a duplication from
locator2
If I were to display them in their short name, it is as follows:
locator1
locator2
locator2|locator3
So as mentioned, when I tried to replace the word 'locator' to 'Point', the
renaming works for locator 1 and 2, but when it comes to locator3, I got the
error RuntimeError: No object matches name
As such, I was wondering if there is a better way for me to recode, cause in
cases like in Modelling, where artists duplicates the object over and over again
or using of instances..
I know that this fails is due to the short name in itself but is it possible to bypass it?
def searchReplace(self):
wordSearch = str(self.searchTxt.text())
wordReplace = str(self.replaceTxt.text())
objCnt = cmds.ls(sl=True, sn=True)
if len(objCnt) == 0:
self.searchTxt.clear()
self.replaceTxt.clear()
cmds.warning('Nothing is selected')
else:
for wordString in sorted(objCnt):
if wordSearch in wordString:
newWordString = wordString.replace(wordSearch, wordReplace)
cmds.rename(wordString, newWordString)
self.searchTxt.clear()
self.replaceTxt.clear()
print '%s' %wordString + " has changed to : " + "%s" %newWordString
This is a tricky problem, but the solution is actually really simple!
When you sort objCnt, you're doing it lexicographically:
for wordString in sorted(objCnt):
This means that locator2 comes before locator2|locator3. On its own that should be fine, but...
When locator2 is renamed, the path to locator3 has also changed, so accessing it fails.
The trick is to reverse the sort so longer objects come first. That way the children always get renamed before their parents
for wordString in sorted(objCnt, reverse=True):
For this to work, you also need to make sure your ls gives you long names, be adding the long=True argument
Related
i tried to replace spaces in a variable in python but it returns me this error
AttributeError: 'HTTPHeaders' object has no attribute 'replace'
this is my code
for req in driver.requests:
print(req.headers)
d = req.headers
x = d.replace("""
""", "")
So, if you check out the class HTTPHeaders you'll see it has a __repr__ function and that it's an HTTPMessage object.
Depending on what you exactly want to achieve (which is still not clear to me!, i.e, for which header do you want to replace spaces?) you can go about this two ways. Use the methods on the HTTPMessage object (documented here) or use the string version of it by calling repr on the response. I recommend you use the first approach as it is much cleaner.
I'll give an example in which I remove spaces for all canary values in all of the requests:
for req in driver.requests:
canary = req.headers.get("canary")
canary = canary.replace(" ", "")
P.S., your question is nowhere near clear enough as it stands. Only after asking multiple times and linking your other question it becomes clear that you are using seleniumwire, for example. Ideally, the code you provide can be run by anyone with the installed packages and reproduces the issue you have. BUT, allright, the comments made it more clear.
I'm new to Python but am very confused as to how this code works:
Correct code I don't understand:
I don't understand how in the function, you can just write ".org' in domain to capture whether the referrer_domain is an organization. I thought you would have to filter via .str.contains() to be able to see if the domain includes .org or .com.
I originally coded:
dot_org = data[data['referrer_domain'].str.contains('.org')
dot_com = data[data['referrer_domain'].str.contains('.com')
def domain_type(type):
if type in dot_org['referrer_domain']:
return 'organization'
elif type in dot_com['referrer_domain']:
return 'company'
else:
return 'other'
data['new_column'] = data['referrer_domain'].apply(domain_type)
But this ended up labeling all of the rows in the new column I created as "other".
Is anyone able to explain why the code in the picture works, but why the code above doesn't?
First, you should not use type as a variable name, because it's a reserved word.
Aside from that, there is no str.contains method, at least not in plain Python. The official way of checking if a string contains another string is using the in operator.
I am not well versed at python at all. I was asked to review someone else's python script that uses search ldap entries. Btw - I can't reach out to original developer for some reason and before it is deployed + tested visual code checking is required. With that constraints in mind, allow me to proceed.
import ldap3
from ldap3 import Server,Connection, ALL
conn = Connection(....)
conn.search(....)
for entry in conn.entries:
if (len(entry['cn']) > 0):
....
name = entry['name']
if name:
user_name = str(name)
else:
user_name = "Bob"
First question is len(entry['cn']) > 0 I like to interpret it as checking the length of characters of returned cn value from ldap e.g. cn=bob,ou=people,ou=foocomany. I am pretty sure entry['cn'] is NOT string type but I don't know what data type it represents. Can you tell me what type it is?
My 2nd + 3rd questions are not directly related to the original question, but plz bear with me asking for them with grace.
My 2nd question is, if that assumption is correct, entry['cn'] should be converted to string type like str(entry['cn']). Then check its length?
My 3rd question is on if stmt. I like to interpret it as if name is not null or if name is not None in pythonic way. Did I interpret it correctly? If so I should replace it as if not (name is None) would work? I googled on it to get that stmt.
Given the context and code provided, it looks like this snippet is using the ldap3 library.
From the relevant documentation, conn.entries should be a list of Entry objects.
This means that entry['cn'] should be returning an Attribute. Doing a bit of source diving, this appears to just be a fancy list with writable flags. len(entry['cn']) > 0 ends up calling this method, which just returns the number of values that attribute has. It being greater than 0 just ensuring that the cn is, in fact, set.
I am trying to write up a script on incremental saves but there are a few hiccups that I am running into.
If the file name is "aaa.ma", I will get the following error - ValueError: invalid literal for int() with base 10: 'aaa' # and it does not happens if my file is named "aaa_0001"
And this happens if I wrote my code in this format: Link
As such, to rectify the above problem, I input in an if..else.. statement - Link, it seems to have resolved the issue on hand, but I was wondering if there is a better approach to this?
Any advice will be greatly appreciated!
Use regexes for better flexibility especially for file rename scripts like these.
In your case, since you know that the expected filename format is "some_file_name_<increment_number>", you can use regexes to do the searching and matching for you. The reason we should do this is because people/users may are not machines, and may not stick to the exact naming conventions that our scripts expect. For example, the user may name the file aaa_01.ma or even aaa001.ma instead of aaa_0001 that your script currently expects. To build this flexibility into your script, you can use regexes. For your use case, you could do:
# name = lastIncFile.partition(".")[0] # Use os.path.split instead
name, ext = os.path.splitext(lastIncFile)
import re
match_object = re.search("([a-zA-Z]*)_*([0-9]*)$", name)
# Here ([a-zA-Z]*) would be group(1) and would have "aaa" for ex.
# and ([0-9]*) would be group(2) and would have "0001" for ex.
# _* indicates that there may be an _, or not.
# The $ indicates that ([0-9]*) would be the LAST part of the name.
padding = 4 # Try and parameterize as many components as possible for easy maintenance
default_starting = 1
verName = str(default_starting).zfill(padding) # Default verName
if match_object: # True if the version string was found
name = match_object.group(1)
version_component = match_object.group(2)
if version_component:
verName = str(int(version_component) + 1).zfill(padding)
newFileName = "%s_%s.%s" % (name, verName, ext)
incSaveFilePath = os.path.join(curFileDir, newFileName)
Check out this nice tutorial on Python regexes to get an idea what is going on in the above block. Feel free to tweak, evolve and build the regex based on your use cases, tests and needs.
Extra tips:
Call cmds.file(renameToSave=True) at the beginning of the script. This will ensure that the file does not get saved over itself accidentally, and forces the script/user to rename the current file. Just a safety measure.
If you want to go a little fancy with your regex expression and make them more readable, you could try doing this:
match_object = re.search("(?P<name>[a-zA-Z]*)_*(?P<version>[0-9]*)$", name)
name = match_object.group('name')
version_component = match_object('version')
Here we use the ?P<var_name>... syntax to assign a dict key name to the matching group. Makes for better readability when you access it - mo.group('version') is much more clearer than mo.group(2).
Make sure to go through the official docs too.
Save using Maya's commands. This will ensure Maya does all it's checks while and before saving:
cmds.file(rename=incSaveFilePath)
cmds.file(save=True)
Update-2:
If you want space to be checked here's an updated regex:
match_object = re.search("(?P<name>[a-zA-Z]*)[_ ]*(?P<version>[0-9]*)$", name)
Here [_ ]* will check for 0 - many occurrences of _ or (space). For more regex stuff, trying and learn on your own is the best way. Check out the links on this post.
Hope this helps.
I'm probably going about this all wrong but...
I am trying to populate a QTreeView from SQL data - using QAbstractItemModel (and having a great deal of trouble understanding it tbh). One of the tutorials I am following (the simplest) populates the Tree by simply calling new instances of the 'Node' and generating the model from the list. The Node has a name and a parentnode (as below). This is OK where you are generating the data within the program. This I can just about follow :)
However, I want to bring the data in from the table and use a string to identify the correct parentnode - mainly because if I am iterating over the records I won't be able to name each one using a separate variable(?). It will be for x in recs: node = Node("name", parentnode).
When I do this, I get the obvious error message that the string isnt the correct object and has no methods. Is there a way of using a string derived from my table to identify the correct 'parent' object (either that, or could somebody point me in the direction of a very basic Qtreeview model tutorial designed for very enthusiastic, but not necessary gifted learners).
rootNode = Node("Hips")
childNode0 = TransformNode("RightPirateLeg", rootNode)
childNode1 = Node("RightPirateLeg_END", childNode0)
childNode2 = CameraNode("LeftFemur", rootNode)
childNode3 = Node("LeftTibia", childNode2)
childNode4 = Node("LeftFoot", childNode3)
childNode5 = LightNode("LeftFoot_END", childNode4)
I realise that I am probably running before I can walk here and apologise in advance for my ignorance.
Are the strings the names of global variables? If so, you can access the value refenced by the global variable with globals()['name'], (replacing 'name' with the string name of the variable of course.)
Or, better yet, instead of littering variable names all over your global namespace
you could use a dict:
node={}
node['rootNode']=Node('Hips')
node['childNode0']=TransformNode('RightPirateLeg',node['rootNode'])
...
This makes it very easy to map between string names and values.