Variable replacement in dictionary - python
I have two formats:
queryString = "{'queryString': 'ipAddress:%ipAddress'}"
qs2 = "{'resourceNetworkInterface':[{'ipAddress': %ipAddress}]}"
They were originally dictionaries, which had been converted to string so as to generate the proper format code. I have been trying this regex pattern to replace the variable (%ipAddress) with .format(IpAddress) specifier. This is a part of a code generation functionality.
queryString = "{'queryString': 'ipAddress:%ipAddress'}"
qs2 = "{'resourceNetworkInterface':[{'ipAddress': %ipAddress}]}"
au_variable_pattern = "%[a-zA-Z$_][a-zA-Z0-9$_]*"
def insert_placeholder_for_au(match_obj):
if match_obj.group() is not None:
print(match_obj.group()[1:])
return "'{}'.format(" + str(match_obj.group()[1:]) + ")"
# return f'f"{{{match_obj.group()[1:]}}}"'
res_str = re.sub(au_variable_pattern,
insert_placeholder_for_au, qs2)
print(res_str)
The second querystring is getting generated correctly as:
{'resourceNetworkInterface':[{'ipAddress': '{}'.format(ipAddress)}]}
While the first queryString is not getting generated correctly:
{'queryString': 'ipAddress:'{}'.format(ipAddress)'}
I am trying to write a generalized solution that can work with variables inside any dictionary structure. How can this be done?
Related
Python - Possibly Regex - How to replace part of a filepath with another filepath based on a match?
I'm new to Python and relatively new to programming. I'm trying to replace part of a file path with a different file path. If possible, I'd like to avoid regex as I don't know it. If not, I understand. I want an item in the Python list [] before the word PROGRAM to be replaced with the 'replaceWith' variable. How would you go about doing this? Current Python List [] item1ToReplace1 = \\server\drive\BusinessFolder\PROGRAM\New\new.vb item1ToReplace2 = \\server\drive\BusinessFolder\PROGRAM\old\old.vb Variable to replace part of the Python list path replaceWith = 'C:\ProgramFiles\Microsoft\PROGRAM' Desired results for Python List []: item1ToReplace1 = C:\ProgramFiles\Micosoft\PROGRAM\New\new.vb item1ToReplace2 = C:\ProgramFiles\Micosoft\PROGRAM\old\old.vb Thank you for your help.
The following code does what you ask, note I updated your '' to '\', you probably need to account for the backslash in your code since it is used as an escape character in python. import os item1ToReplace1 = '\\server\\drive\\BusinessFolder\\PROGRAM\\New\\new.vb' item1ToReplace2 = '\\server\\drive\\BusinessFolder\\PROGRAM\\old\\old.vb' replaceWith = 'C:\ProgramFiles\Microsoft\PROGRAM' keyword = "PROGRAM\\" def replacer(rp, s, kw): ss = s.split(kw,1) if (len(ss) > 1): tail = ss[1] return os.path.join(rp, tail) else: return "" print(replacer(replaceWith, item1ToReplace1, keyword)) print(replacer(replaceWith, item1ToReplace2, keyword)) The code splits on your keyword and puts that on the back of the string you want. If your keyword is not in the string, your result will be an empty string. Result: C:\ProgramFiles\Microsoft\PROGRAM\New\new.vb C:\ProgramFiles\Microsoft\PROGRAM\old\old.vb
One way would be: item_ls = item1ToReplace1.split("\\") idx = item_ls.index("PROGRAM") result = ["C:", "ProgramFiles", "Micosoft"] + item_ls[idx:] result = "\\".join(result) Resulting in: >>> item1ToReplace1 = r"\\server\drive\BusinessFolder\PROGRAM\New\new.vb" ... # the above >>> result 'C:\ProgramFiles\Micosoft\PROGRAM\New\new.vb' Note the use of r"..." in order to avoid needing to have to 'escape the escape characters' of your input (i.e. the \). Also that the join/split requires you to escape these characters with a double backslash.
How to add string in specific positions in geojson object
i have the below posted geojson mentioned in geojson_1 section below. i want to add to it "geometry":{ and }, so that to appear as follows {"geometry":{"type":"Polygon","coordinates":[[[1216374.67364018,6563498.44078949],[1216387.86261675,6563523.87797899],[1216397.66970116,6563548.2905649],[1216424.17569103,6563588.32082324],[1216458.19258303,6563622.16452455],[1216498.32084288,6563648.42909789],[1216542.90943577,6563666.03380959],[1216590.12376481,6563674.25425166],[1216638.02117068,6563672.7521636],[1216684.63088244,6563661.58935797],[1216728.03512655,6563641.225175],[1216752.29181681,6563626.67066235],[1216787.17700448,6563601.12371718],[1216816.83970763,6563569.63465531],[1216831.39332728,6563551.03748989],[1216838.2508451,6563541.8226918],[1216897.47283376,6563458.0765492],[1216918.74007329,6563421.44644481],[1216933.156564,6563381.60258193],[1216940.26085904,6563339.82061228],[1216939.82562707,6563297.43819918],[1216931.86491641,6563255.81218836],[1216907.60647856,6563170.91644364],[1216887.20280767,6563121.46139137],[1216856.24799209,6563077.86160203],[1216821.48046704,6563039.0529759],[1216799.23490474,6563017.28929875],[1216753.95673639,6562978.48086898],[1216737.29066155,6562965.4435638],[1216673.22488836,6562919.79826372],[1216644.73178636,6562899.22061724],[1216601.13622245,6562874.31962206],[1216562.32695185,6562857.3410734],[1216556.56069412,6562854.90900462],[1216549.97837146,6562852.23502385],[1216545.77480552,6562849.58841453],[1216504.75306873,6562829.03095075],[1216487.0229317,6562822.21187019],[1216482.65368148,6562820.3796627],[1216478.79578194,6562814.49158384],[1216462.95127963,6562793.04723497],[1216450.44559886,6562777.97698661],[1216448.65520854,6562774.19751598],[1216429.39331353,6562740.84427663],[1216404.99213055,6562711.06486155],[1216382.3528849,6562687.61801865],[1216357.97638417,6562665.64947943],[1216339.38004804,6562651.09634054],[1216299.24217837,6562625.743469],[1216254.86196793,6562608.94292463],[1216208.02902037,6562601.37212065],[1216160.63182011,6562603.33631786],[1216114.58159971,6562614.75632195],[1216071.73529105,6562635.17167463],[1216033.82066317,6562663.75921023],[1216002.36666225,6562699.36623124],[1215978.64176027,6562740.55696848],[1215963.60279766,6562785.67045603],[1215957.85638339,6562832.88749107],[1215961.63441126,6562880.30398198],[1215963.25125904,6562889.19806131],[1215964.03213898,6562893.28933659],[1215968.1319511,6562913.79137984],[1215972.03222389,6562937.19708669],[1215977.28745991,6563016.79645952],[1215971.45390521,6563048.0427099],[1215969.39172682,6563061.09023781],[1215963.73069651,6563104.75131293],[1215962.06592533,6563123.22251112],[1215960.00953034,6563163.6421848],[1215954.35640427,6563213.80082903],[1215954.63230125,6563269.34572034],[1215960.29082704,6563315.43307246],[1215970.70253119,6563361.57391952],[1215982.82982632,6563397.95907391],[1216001.20120538,6563439.38870108],[1216027.10825421,6563476.54992802],[1216059.60193364,6563508.08124916],[1216097.4918555,6563532.82739871],[1216139.38989254,6563549.8816932],[1216183.76104002,6563558.61926572],[1216228.97966418,6563558.71997125],[1216273.38907516,6563550.18012236],[1216287.1346647,6563546.13717455],[1216332.92682121,6563527.24586381],[1216373.78586258,6563499.1986745],[1216374.67364018,6563498.44078949]]]}} to simpify it even more, i want to add "geometry":{ right after the the first curly bracket, and the } at the very end i attmepted the following: asString = asString[:2] + "geometry:" + asString[2:] asString = asString[:len(asString)] + "}" + asString[len(asString):] but i am not getting the expected results geojson_1: {"type":"Polygon","coordinates":[[[1216374.67364018,6563498.44078949],[1216387.86261675,6563523.87797899],[1216397.66970116,6563548.2905649],[1216424.17569103,6563588.32082324],[1216458.19258303,6563622.16452455],[1216498.32084288,6563648.42909789],[1216542.90943577,6563666.03380959],[1216590.12376481,6563674.25425166],[1216638.02117068,6563672.7521636],[1216684.63088244,6563661.58935797],[1216728.03512655,6563641.225175],[1216752.29181681,6563626.67066235],[1216787.17700448,6563601.12371718],[1216816.83970763,6563569.63465531],[1216831.39332728,6563551.03748989],[1216838.2508451,6563541.8226918],[1216897.47283376,6563458.0765492],[1216918.74007329,6563421.44644481],[1216933.156564,6563381.60258193],[1216940.26085904,6563339.82061228],[1216939.82562707,6563297.43819918],[1216931.86491641,6563255.81218836],[1216907.60647856,6563170.91644364],[1216887.20280767,6563121.46139137],[1216856.24799209,6563077.86160203],[1216821.48046704,6563039.0529759],[1216799.23490474,6563017.28929875],[1216753.95673639,6562978.48086898],[1216737.29066155,6562965.4435638],[1216673.22488836,6562919.79826372],[1216644.73178636,6562899.22061724],[1216601.13622245,6562874.31962206],[1216562.32695185,6562857.3410734],[1216556.56069412,6562854.90900462],[1216549.97837146,6562852.23502385],[1216545.77480552,6562849.58841453],[1216504.75306873,6562829.03095075],[1216487.0229317,6562822.21187019],[1216482.65368148,6562820.3796627],[1216478.79578194,6562814.49158384],[1216462.95127963,6562793.04723497],[1216450.44559886,6562777.97698661],[1216448.65520854,6562774.19751598],[1216429.39331353,6562740.84427663],[1216404.99213055,6562711.06486155],[1216382.3528849,6562687.61801865],[1216357.97638417,6562665.64947943],[1216339.38004804,6562651.09634054],[1216299.24217837,6562625.743469],[1216254.86196793,6562608.94292463],[1216208.02902037,6562601.37212065],[1216160.63182011,6562603.33631786],[1216114.58159971,6562614.75632195],[1216071.73529105,6562635.17167463],[1216033.82066317,6562663.75921023],[1216002.36666225,6562699.36623124],[1215978.64176027,6562740.55696848],[1215963.60279766,6562785.67045603],[1215957.85638339,6562832.88749107],[1215961.63441126,6562880.30398198],[1215963.25125904,6562889.19806131],[1215964.03213898,6562893.28933659],[1215968.1319511,6562913.79137984],[1215972.03222389,6562937.19708669],[1215977.28745991,6563016.79645952],[1215971.45390521,6563048.0427099],[1215969.39172682,6563061.09023781],[1215963.73069651,6563104.75131293],[1215962.06592533,6563123.22251112],[1215960.00953034,6563163.6421848],[1215954.35640427,6563213.80082903],[1215954.63230125,6563269.34572034],[1215960.29082704,6563315.43307246],[1215970.70253119,6563361.57391952],[1215982.82982632,6563397.95907391],[1216001.20120538,6563439.38870108],[1216027.10825421,6563476.54992802],[1216059.60193364,6563508.08124916],[1216097.4918555,6563532.82739871],[1216139.38989254,6563549.8816932],[1216183.76104002,6563558.61926572],[1216228.97966418,6563558.71997125],[1216273.38907516,6563550.18012236],[1216287.1346647,6563546.13717455],[1216332.92682121,6563527.24586381],[1216373.78586258,6563499.1986745],[1216374.67364018,6563498.44078949]]]}
I'm going to assume that geojson_1 is available as a string in which case: import json output = {'geometry': json.loads(geojson_1)} ...will give you a dictionary with the structure you need.
It looks like plain json data, or a string representation of a dict (they wouldn't be any different in this case), did you consider wrapping the returned data in a new dict rather than manipulating it as a string? import json # Assume this returns the geojson as text geojson = json.loads(get_geojson()) geojson = {"geometry": geojson} print(json.dumps(geojson))
I get the expected result using the following: '{"geometry":' + d + "}" It adds the string {"geometry": to the string d and at the end }. The variable dis: d = '{"type":"Polygon","co (rest of json) ,6563498.44078949]]]}' Or you can use the json library for this: import json data = json.loads(d) # note d is the same string as above, this can also be from a file or read file using json.load(FILE) # Create your new object: result = {'geometry': data} # print you new json: print( json.dumps(result, indent=2)) edit: '"geometry":{' + d + "}" Note that you get a string starting with geometry and a { and directly another { from you input json. This is not a correct dictionary nor a proper json format. Result: '"geometry":{{"type":"Polygon", ... ,6563498.44078949]]]}}' (the dots are just the rest of your original json.
Are multiple operations for string formatting allowed in Python?
Could be a basic one: I am just trying to do multiple operations on one of the key in a dictionary with encoding the first element of the key, splitting it further based on a character and also joining with another string as below: images_list["RepoTag"] = image["RepoDigests"][0].encode("utf-8").split("#")[0] + ":none" Code snippet in which I am doing the above formatting: from django.http import JsonResponse from django.views.decorators.http import require_http_methods import requests #require_http_methods(["GET"]) def images_info(request): response = requests.get("http://127.0.0.1:6000/images/json") table = [] images_list = {} for image in response.json(): try: images_list["RepoTag"] = image["RepoTags"][0].encode("utf-8") except TypeError: images_list["RepoTag"] = image["RepoDigests"][0].encode("utf-8").split("#")[0] + ":none" images_list["Id"] = image["Id"].encode("utf-8")[7:19] table.append(images_list) images_list = {} return JsonResponse(table,safe=False) Can someone tell me whether is it the right way to do these many operations in a single line? or in another way Does it follows the python standards ? If not does python standards suggest any limited operations in a single line or so? Reason for asking this is that the number of characters should not exceed 79 characters as per pep-8.
There's nothing wrong with chaining a few string operations together. If you want to keep it within the 80-character line, just add some parentheses: images_list["RepoTag"] = ( image["RepoDigests"][0].encode("utf-8").split("#")[0] + ":none") or use str.format() to provide those same parentheses: images_list["RepoTag"] = '{}:none'.format( image["RepoDigests"][0].encode("utf-8").split("#")[0]) You could, otherwise, trivially use a local variable: first_digest = image["RepoDigests"][0].encode("utf-8") images_list["RepoTag"] = '{}:none'.format(first_digest.split("#")[0])
It is asked not to exceed 79 characters, but we can do it. images_list["RepoTag"] = image["RepoDigests"][0].encode("utf-8").split("#")[0] + \ ":none" OR images_list["RepoTag"] = \ image["RepoDigests"][0].encode("utf-8").split("#")[0] + ":none"
pyparsing: skip to the next token ignoring everything in between
I am trying to parse a log file that contains multiple entries with the following format: ITEM_BEGIN item_name some_text some_text may optionally contain an expression matched by my_expr anywhere within itself. I am only interested in item_name and my_expr (or None if it is missing). Ideally, what I want is a list of (item_name, my_expr) pairs. What is the best way to extract this information using pyparsing?
If you are not trying to define a parser for the entire input text, but only some pieces of it, look into using pyparsing's searchString or scanString methods - something along these lines: import pyparsing as pp ident = Word(alphas, alphanums+'_') item_header = pp.Keyword("ITEM_BEGIN") + ident("name") other_expr = ... whatever ... search_expr = item_header | other_expr found = {} current_name = '' for result in search_expr.searchString(input_text): result = result[0] if result[0] == "ITEM_BEGIN": print("found an item header with name {name}".format_map(result)) current_name = result.name found[result.name] = [] else: # found an other expr found[current_name].append(result.asList())
Python templates for generating Python code with proper multiline indentation
I'm using Python to compile another Python file. To this end, I use Template from string into which I insert, e.g., a constructed function body, e.g., from string import Template s = Template(''' def main(): ${body} return ''') # body constructed bit by bit body = ['a'] body.append('b') body.append('c') out = s.substitute(body='\n'.join(body)) print(out) The output of the above is def main(): a b c return which already highlights the problem: ${body} lines other than the first aren't correctly indented. I could of course manually add the spaces when inserting 'b' and 'c' into the body list, but that already assumes knowledge of the template into which the body will be inserted. (Perhaps string.Template is not be the appropriate template engine to begin with.)
Assuming you need to fix indentation for multi line replacements only when the ${} model is at the beginning of the line (except for the indentation), you could use a regex to find all the tokens in the mask and if they are preceded with only blanks repeat them on all following lines from the replacement list. You could use code like that: import string, re def substitute(s, reps): t = string.Template(s) i=0; cr = {} # prepare to iterate through the pattern string while True: # search for next replaceable token and its prefix m =re.search(r'^(.*?)\$\{(.*?)\}', tpl[i:], re.MULTILINE) if m is None: break # no more : finished # the list is joined using the prefix if it contains only blanks sep = ('\n' + m.group(1)) if m.group(1).strip() == '' else '\n' cr[m.group(2)] = sep.join(rep[m.group(2)]) i += m.end() # continue past last processed replaceable token return t.substitute(cr) # we can now substitute With your example (slightly modified), it would give: s = ''' def main(): ${body} return ${retval} ''') # body constructed bit by bit body = ['a'] body.append('b') body.append('c') out = substitute(s, { 'body': body, 'retval': 0 } print (out) it gives as expected: def main(): a b c return 0