I have input which looks like the following 2 lines:
TASK1,6,INITIAL,2013-01-15 19:20:40,PREPARING,2013-01-15 19:21:12,SCHEDULED,2013-01-15 19:21:13,TRANSLATING,2013-01-15 19:21:13,LOADING,2013-01-15 19:36:37,COMPLETE,2013-01-15 19:36:42
TASK2,5,INITIAL,2013-01-15 19:20:44,PREPARING,2013-01-15 19:21:13,SCHEDULED,2013-01-15 19:21:14,TRANSLATING,2013-01-15 19:36:37,TERMINAL,2013-01-15 20:28:10
I need to loop through a file with these lines and for each line calculate several time differences... i'm fine on the calculations and such, but i'm having a devil of a time trying to figure out how to parse this "variable length" string of name value pairs...
Basically the # after the Task# is the count of "statuses" followed by those statuses and their occuring time.
What i'd like to do is get one of the lines and end up with something like this having the values assigned to their respective variables. (using first line as example):
$TASK_ID=TASK1
$STATUS_COUNT=6
$INITIAL=2013-01-15 19:20:40
$PREPARING=2013-01-15 19:21:12
$SCHEDULED=2013-01-15 19:21:12
$TRANSLATING=2013-01-15 19:21:13
$LOADING=2013-01-15 19:36:37
$COMPLETE=2013-01-15 19:36:42
$TERMINAL=<NULL>
Compounding the problem is that if a task is submitted more than once it will simply append the next round of statuses to the first set meaning i could end up with an input line like:
TASK1,11,INITIAL,2013-01-15 19:20:40,PREPARING,2013-01-15 19:21:12,SCHEDULED,2013-01-15 19:21:13,TRANSLATING,2013-01-15 19:21:13,LOADING,2013-01-15 19:36:37,COMPLETE,2013-01-15 19:36:42,INITIAL,2013-01-15 20:20:40,PREPARING,2013-01-15 20:21:12,SCHEDULED,2013-01-15 20:21:13,TRANSLATING,2013-01-15 20:21:13,TERMINAL,2013-01-15 20:36:42
I this case i would want my output to be:
$TASK_ID=TASK1
$STATUS_COUNT=11
$INITIAL=2013-01-15 20:20:40
$PREPARING=2013-01-15 20:21:12
$SCHEDULED=2013-01-15 20:21:12
$TRANSLATING=2013-01-15 20:21:13
$LOADING=<NULL>
$COMPLETE=<NULL>
$TERMINAL=2013-01-15 20:36:42
I'm pretty stumped on this, can anyone help?
Thanks in advance
#!/bin/bash
# Splitting on commas, read the task ID and status count followed by all of the statuses,
# which we'll parse later.
while IFS=, read -r TASK_ID STATUS_COUNT STATUSES; do
(
# Subtly, but importantly, we put the loop body inside parentheses so each loop
# iteration runs in a sub-shell. This ensures that the $LOADING, $COMPLETE, etc.
# variables we set don't leak into future iterations.
echo "TASK_ID = $TASK_ID"
echo "STATUS_COUNT = $STATUS_COUNT"
# Convert the comma-separated string $STATUSES into an array using `read -a'.
IFS=, read -ra STATUSES <<< "$STATUSES"
# Assign the statuses to named variables. A side benefit of this is that only the
# last value of each status type is used.
for ((i = 0; i < ${#STATUSES[#]}; i += 2)); do
declare "${STATUSES[$i]}=${STATUSES[$((i+1))]}"
done
# Print each of the statuses, or <NULL> if that stage wasn't listed.
echo "INITIAL = ${INITIAL:-<NULL>}"
echo "PREPARING = ${PREPARING:-<NULL>}"
echo "SCHEDULED = ${SCHEDULED:-<NULL>}"
echo "TRANSLATING = ${TRANSLATING:-<NULL>}"
echo "LOADING = ${LOADING:-<NULL>}"
echo "COMPLETE = ${COMPLETE:-<NULL>}"
echo "TERMINAL = ${TERMINAL:-<NULL>}"
echo
)
done
Output:
$ ./tasks < tasks.txt
TASK_ID = TASK1
STATUS_COUNT = 6
INITIAL = 2013-01-15 19:20:40
PREPARING = 2013-01-15 19:21:12
SCHEDULED = 2013-01-15 19:21:13
TRANSLATING = 2013-01-15 19:21:13
LOADING = 2013-01-15 19:36:37
COMPLETE = 2013-01-15 19:36:42
TERMINAL = <NULL>
TASK_ID = TASK2
STATUS_COUNT = 5
INITIAL = 2013-01-15 19:20:44
PREPARING = 2013-01-15 19:21:13
SCHEDULED = 2013-01-15 19:21:14
TRANSLATING = 2013-01-15 19:36:37
LOADING = <NULL>
COMPLETE = <NULL>
TERMINAL = 2013-01-15 20:28:10
TASK_ID = TASK1
STATUS_COUNT = 11
INITIAL = 2013-01-15 20:20:40
PREPARING = 2013-01-15 20:21:12
SCHEDULED = 2013-01-15 20:21:13
TRANSLATING = 2013-01-15 20:21:13
LOADING = 2013-01-15 19:36:37
COMPLETE = 2013-01-15 19:36:42
TERMINAL = 2013-01-15 20:36:42
(Glenn Jackman adding edit based on new requirement)
events=(INITIAL PREPARING SCHEDULED TRANSLATING LOADING COMPLETE TERMINAL)
while IFS=, read -r TASK_ID STATUS_COUNT rest; do
IFS=, read -ra STATUSES <<< "$rest"
for (( i=0; i < ${#STATUSES[#]}; i+=2 )); do
# if this this the initial event, reset all statuses
if [[ ${STATUSES[i]} == ${events[0]} ]]; then
for event in "${events[#]}"; do
declare "$event="
done
fi
declare "${STATUSES[i]}=${STATUSES[i+1]}"
done
for var in TASK_ID STATUS_COUNT "${events[#]}"; do
printf "$%s = %s\n" $var "${!var:-<NULL>}"
done
done
Related
About once a month I get a google drive folder with lots of videos in it (usually around 700-800) and a spreadsheet that column A gets populated with the names of all of the video files in order of the time stamp in the video file name. Now I've already got the code that does this (I will post it below) but This time I've got about 8,400 video files in the folder and this algorithm has a pageSize limit of 1,000 (it was originally 100, I changed it to 1,000 but that's the highest it will accept) How do I change this code to accept more than 1000
This is the part that initializes everything
!pip install gspread_formatting
import time
import gspread
from gspread import urls
from google.colab import auth
from datetime import datetime
from datetime import timedelta
from gspread_formatting import *
from googleapiclient.discovery import build
from oauth2client.client import GoogleCredentials
from google.auth import default
folder_id = '************************' # change to whatever folder the required videos are in
base_dir = '/Example/drive/videofolder' # change this to whatever folder path you want to grab videos from same as above
file_name_qry_filter = "name contains 'mp4' and name contains 'cam'"
file_pattern="cam*.mp4"
spreadSheetUrl = 'https://docs.google.com/spreadsheets/d/SpreadsheetIDExample/edit#gid=0'
data_drive_id = '***********' # This is the ID of the shared Drive
auth.authenticate_user()
creds, _ = default()
gc = gspread.authorize(creds)
#gc = gspread.authorize(GoogleCredentials.get_application_default())
wb = gc.open_by_url(spreadSheetUrl)
sheet = wb.worksheet('Sheet1')
And this is the main part of the code
prevTimeStamp = None
prevHour = None
def dateChecker(fileName, prevHour):
strippedFileName = fileName.strip(".mp4") # get rid of the .mp4 from the end of the file name
parsedFileName = strippedFileName.split("_") # split the file name into an array of (0 = Cam#, 1 = yyyy-mm-dd, 2 = hh-mm-ss)
timeStamp = parsedFileName[2] # Grabbed specifically the hh-mm-ss time section from the original file name
parsedTimeStamp = timeStamp.split("-") # split the time stamp into an array of (0 = hour, 1 = minute, 2 = second)
hour = int(parsedTimeStamp[0])
minute = int(parsedTimeStamp[1])
second = int(parsedTimeStamp[2]) # set hour, minute, and seccond to it's own variable
commentCell = "Reset"
if prevHour == None:
commentCell = " "
prevHour = hour
else:
if 0 <= hour < 24:
if hour == 0:
if prevHour == 23:
commentCell = " "
else:
commentCell = "Missing Video1"
else:
if hour - prevHour == 1:
commentCell = " "
else:
commentCell = "Missing Video2"
else:
commentCell = "Error hour is not between 0 and 23"
if minute != 0 or 1 < second <60:
commentCell = "Check Length"
prevHour = hour
return commentCell, prevHour
# Drive query variables
parent_folder_qry_filter = "'" + folder_id + "' in parents" #you shouldn't ever need to change this
query = file_name_qry_filter + " and " + parent_folder_qry_filter
drive_service = build('drive', 'v3')
# Build request and call Drive API
page_token = None
response = drive_service.files().list(q=query,
corpora='drive',
supportsAllDrives='true',
includeItemsFromAllDrives='true',
driveId=data_drive_id,
pageSize=1000,
fields='nextPageToken, files(id, name, webViewLink)', # you can add extra fields in the files() if you need more information about the files you're grabbing
pageToken=page_token).execute()
i = 1
array = [[],[]]
# Parse/print results
for file in response.get('files', []):
array.insert(i-1, [file.get('name'), file.get('webViewLink')]) # If you add extra fields above, this is where you will have to start changing the code to make it accomadate the extra fields
i = i + 1
array.sort()
array_sorted = [x for x in array if x] #Idk man this is some alien shit I just copied it from the internet and it worked, it somehow removes any extra blank objects in the array that aren't supposed to be there
arrayLength = len(array_sorted)
print(arrayLength)
commentCell = 'Error'
# for file_name in array_sorted:
# date_gap, start_date, end_date = date_checker(file_name[0])
# if prev_end_date == None:
# print('hello')
# elif start_date != prev_end_date:
# date_gap = 'Missing Video'
for file_name in array_sorted:
commentCell, prevHour = dateChecker(file_name[0], prevHour)
time.sleep(0.3)
#insertRow = [file_name[0], "Not Processed", " ", date_gap, " ", " ", " ", " ", base_dir + '/' + file_name[0], " ", file_name[1], " ", " ", " "]
insertRow = [file_name[0], "Not Processed", " ", commentCell, " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]
sheet.append_row(insertRow, value_input_option='USER_ENTERED')
Now I know the problem has to do with the
page_token = None
response = drive_service.files().list(q=query,
corpora='drive',
supportsAllDrives='true',
includeItemsFromAllDrives='true',
driveId=data_drive_id,
pageSize=1000,
fields='nextPageToken, files(id, name, webViewLink)', # you can add extra fields in the files() if you need more information about the files you're grabbing
pageToken=page_token).execute()
In the middle of the main part of the code. I've obviously already tried just changing the pageSize limit to 10,000 but I knew that wouldn't work and I was right, it came back with
HttpError: <HttpError 400 when requesting https://www.googleapis.com/drive/v3/files?q=name+contains+%27mp4%27+and+name+contains+%27cam%27+and+%271ANmLGlNr-Cu0BvH2aRrAh_GXEDk1nWvf%27+in+parents&corpora=drive&supportsAllDrives=true&includeItemsFromAllDrives=true&driveId=0AF92uuRq-00KUk9PVA&pageSize=10000&fields=nextPageToken%2C+files%28id%2C+name%2C+webViewLink%29&alt=json returned "Invalid value '10000'. Values must be within the range: [1, 1000]". Details: "Invalid value '10000'. Values must be within the range: [1, 1000]">
The one idea I have is to have multiple pages with 1000 each and than iterate through them but I barely understood how this part of the code worked a year ago when I set it up and since than I haven't touched google colab except to run this algorithm and Every time I try to google how to do this or look up the google drive API or anything else everything always comes back with how to download and upload a couple file where what I need is just to get a list of the names of all the files.
The documentation explains how to use the pageToken for pagination (the page is for Calendar API but it works the same in Drive):
In order to retrieve the next page, perform the exact same request as previously and append a pageToken field with the value of nextPageToken from the previous page. A new nextPageToken is provided on the following pages until all the results are retrieved.
Essentially you want a loop where you run files.list(), retrieve the pageToken, and run it again while feeding it the previous token until you stop getting tokens.
For your specific scenario you can try to replace the "problem" snippet with the following:
page_token = ""
filelist = {}
while True:
response = drive_service.files().list(q=query,
corpora='drive',
supportsAllDrives='true',
includeItemsFromAllDrives='true',
driveId=data_drive_id,
pageSize=1000,
fields='nextPageToken, files(id, name, webViewLink)',
pageToken=page_token).execute()
page_token = response.get('nextPageToken', None)
filelist.setdefault("files",[]).extend(response.get('files'))
if (not page_token):
break
response = filelist
This does as I described, looping files.list() and adding the results to the filelist variable, then breaking the loop when the API stops returning page tokens. At the end I just assigned the value of filelist to the response variable since that's what you're using in the rest of your code. It should parse the same way but with the full list of results this time.
Sources:
Page through list of resources
Files.list()
I have a properties file which I call inside my Jenkins Pipeline Script to get multiple variables.
BuildCounter = n
BuildName1 = Name 1
BuildName2 = Name 2
...
Buildnamen = Name n
I call my properties file with: def props = readProperties file: Path
Now I want to create a loop to print all my BuildNames
for (i = 0; i < BuildJobCounterInt; i++){
tmp = 'BuildName' + i+1
println props.tmp
}
But of course this is not working. ne last println call is searching for a variable called tmp in my properties file. Is there a way to perform this or am I completely wrong?
EDIT:
This is my .properties file:
BuildJobCounter = 1
BuildName1 = 'Win32'
BuildPath1 = '_Build/MBE3_Win32'
BuildName2 = 'empty'
BuildPath2 = 'empty'
TestJobCounter = '0'
TestName1 = 'empty'
TestPath1 = 'empty'
TestName2 = 'empty'
TestPath2 = 'empty'
In my Jenkins pipeline I want to have the possibility to check the ammount of Build/TestJobs and automatically calle the Jobs (each BuildName and BuildPath is a Freestyle Job) To call all these Job I thought of calling the variables inside a for loop. So for every istep I have the Name/Path pair.
Try the below:
Change from:
println props.tmp
To:
println props[tmp]
or
println props."$tmp"
EDIT : based on OP comment
change from:
tmp = 'BuildName' + i+1
To:
def tmp = "BuildName${(i+1).toString()}"
initially I have to state, that I have little to no experience with powershell so far. A previous system generates the wrong output for me. So I want to use PowerShell to change this. From the System I get an output looking like this:
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^...^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^...^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
When you look at it, there is a starting part for each line (TEST1^|^9999^|^) followed by a1 to a-n tuples (example: Y^|^NOT IN^|^('1','2','3')^|^).
The way I want this to look like is here:
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')
TEST1^|^9999^|^N^|^LIKE^|^('4','5','6','7')
TEST1^|^9999^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')
TEST2^|^9998^|^N^|^LIKE^|^('6','7','8','9')
TEST2^|^9998^|^Y^|^NOT IN^|^('1','2','15','16','17')
TEST2^|^9998^|^Y^|^NOT IN^|^('18','19','20','21','22')
So the tuples shall be printed out per line, with the starting part attached in front.
My solution approach is the AWK equivalent in Powershell, but to date I lack the understanding of how to tackle the issue of how to deal with an indetermined number of tuples and to repeat the starting block.
I thank you so much in advance for your help!
I'd split the lines at ^|^ and recombine the fields of the resulting array in a loop. Something like this:
$sp = '^|^'
Get-Content 'C:\path\to\input.txt' | % {
$a = $_ -split [regex]::Escape($sp)
for ($i=2; $i -lt $a.length; $i+=3) {
"{0}$sp{1}$sp{2}$sp{3}$sp{4}" -f $a[0,1,$i,($i+1),($i+2)]
}
} | Set-Content 'C:\path\to\output.txt'
The data looks quite regular so you could loop over it using | as the delimiter and counting the following cells in 3s:
$data = #"
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
"#
$data.split("`n") | % {
$ds = $_.split("|")
$heading = "$($ds[0])|$($ds[1])"
$j = 0
for($i = 2; $i -lt $ds.length; $i += 1) {
$line += "|$($ds[$i])" -replace "\^(\((?:'\d+',?)+\))\^?",'$1'
$j += 1
if($j -eq 3) {
write-host $heading$line
$line = ""
$j = 0
}
}
}
Parsing an arbitary length string record to row records is quite error prone. A simple solution would be processing the data row-by-row and creating output.
Here is a simple illustration how to process a single row. Processing the whole input file and writing output is left as trivial an exercise to the reader.
$s = "TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')"
$t = $s.split('\)', [StringSplitOptions]::RemoveEmptyEntries)
$testNum = ([regex]::match($t[0], "(?i)(test\d+\^\|\^\d+)")).value # Hunt for 1st colum values
$t[0] = $t[0] + ')' # Fix split char remove
for($i=1;$i -lt $t.Length; ++$i) { $t[$i] = $testNum + $t[$i] + ')' } # Add 1st colum and split char remove
$t
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')
TEST1^|^9999^|^N^|^LIKE^|^('4','5','6','7')
TEST1^|^9999^|^Y^|^NOT IN^|^('8','9','10','11','12')
I have a database of users and each user has its own timezone settings.
For example, user A has GMT-05:00 , user B has GMT+1:00 , etc
I am trying to display the correct current date/time for this users using the simplest way I can find. I got to this code, which although it looks good (imho), it displays a positive difference (+5 hours) instead of negative (minus 5 hours).
Script below:
<?php
// below two lines -- info that I normally take from DB
$row['callstart'] = "1362067791"; // unixtimestamp
$userInfo['timezone'] = 'GMT-5';
echo date('Y-m-d H:i:s',$row['callstart'])."\n"; // original hour
$date = date('Y-m-d H:i:s',$row['callstart']);
$date = new DateTime($date,new DateTimeZone('GMT'));
$date->setTimezone(new DateTimeZone($userInfo['timezone']));
$row['callstart'] = $date->format('Y-m-d H:i:s');
echo $row['callstart']; // converted to GMT-5 hour
?>
Results below:
root#ssw238:/tmp# php /work/yy.php
2013-02-28 16:09:51 // that's the current GMT hour/date
2013-02-28 21:09:51 // should actually be 11:09:51 instead of 21:09:51
root#ssw238:/tmp#
Any idea where and what I am doing wrong?
This is when common sense works against us... From Wikipedia
In order to conform with the POSIX style, those zone names beginning with "Etc/GMT" have their sign reversed from what most people expect. In this style, zones west of GMT have a positive sign and those east have a negative sign in their name (e.g "Etc/GMT-14" is 14 hours ahead/east of GMT.)
So the solution is
// below two lines -- info that I normally take from DB
$row['callstart'] = "1362067791"; // unixtimestamp
// reversed the sign
$userInfo['timezone'] = 'GMT+5';
echo date('Y-m-d H:i:s',$row['callstart'])."\n"; // original hour
$date = date('Y-m-d H:i:s',$row['callstart']);
$date = new DateTime($date,new DateTimeZone('GMT'));
$date->setTimezone(new DateTimeZone($userInfo['timezone']));
$row['callstart'] = $date->format('Y-m-d H:i:s');
echo $row['callstart']; // converted to GMT-5 hour
hmmm ... i rather youse this
<?php
$row['callstart'] = "1362067791";
$userInfo['timezone'] = 'GMT-5';
$orginal =date('Y-m-d H:i:s',$row['callstart']);
echo $orginal;
echo '<br/>';
$newdate=date('Y-m-d H:i:s',($orginal + strtotime(substr($userInfo['timezone'] ,3).'hours')));
echo $newdate
?>
2013-02-28 17:09:51
2013-02-28 13:22:36
As part of debugging a problem that might be related to my UIVIews, I want to write a python script to run from LLDB. I had thought to extract all settings for a view in a breakpoint and all view children, to allow me to compare states. I checked out the WWDC video on the topic and then spent time reading things at lldb.llvm.org/scripting.html, and didn't find them very helpful. A web search for examples led to nothing substantially different from those.
My problem is that I'm trying to figure out how to access iOS variables at my breakpoint. The examples I've seen do things like convert numbers and mimic shell commands. Interesting stuff but not useful for my purposes. I've been reading my way through the help info with "script help(lldb.SBValue)" and the like, but it is slow going as the results are huge and it is not clear what the use patterns are. I feel like one decent example of how to traverse a few iOS objects would help me understand the system. Does anyone know of one or can share a snippet of code?
UPDATE:
I wrote this to help me track down a bug in my UIView use. I want to do a bit more work to refine this to see if I could show the whole view tree, but this was sufficient to solve my problem, so I'll put it here to save others some time.
import lldb
max_depth = 6
filters = {'_view':'UIView *', '_layer':'CALayer *', '_viewFlags':'struct'}
def print_value(var, depth, prefix):
""" print values and recurse """
global max_depth
local_depth = max_depth - depth
pad = ' ' * local_depth
name = var.GetName()
typ = str(var.GetType()).split('\n')[0].split('{')[0].split(':')[0].strip()
found = name in filters.keys() # only visit filter items children
if found:
found = (filters.get(name) == typ)
value = var.GetValue()
if value is None or str(value) == '0x00000000':
value = ''
else:
value = ' Val: %s' % value
if var.GetNumChildren() == 0 and var.IsInScope():
path = lldb.SBStream()
var.GetExpressionPath(path)
path = ' pathData: %s' % path.GetData()
else:
path = ''
print '^' * local_depth, prefix, ' Adr:', var.GetAddress(), ' Name:', name, ' Type:', typ, value, path
if var.GetNumChildren() > 0:
if local_depth < 2 or found:
print pad, var.GetNumChildren(), 'children, to depth', local_depth + 1
counter = 0
for subvar in var:
subprefix = '%d/%d' % (counter, var.GetNumChildren())
print_value(subvar, depth - 1, subprefix)
counter += 1
def printvh (debugger, command_line, result, dict):
""" print view hierarchy """
global max_depth
args = command_line.split()
if len(args) > 0:
var = lldb.frame.FindVariable(args[0])
depth = max_depth
if len(args) > 1:
depth = int(args[1])
max_depth = depth
print_value(var, depth, 'ROOT')
else:
print 'pass a variable name and optional depth'
And I added the following to my .lldbinit :
script import os, sys
# So that files in my dir takes precedence.
script sys.path[:0] = [os.path.expanduser("~/lldbpy")]
script import views
command script add -f views.printvh printvh
so that I can just type "printvh self 3" at the LLDB prompt.
Maybe this will help. Here's an example of how to dump simple local variables when a breakpoint is hit. I'm not displaying char* arrays correctly, I'm not sure how I should get the data for these to display it like "frame variable" would display it but I'll figure that out later when I have a free minute.
struct datastore {
int val1;
int val2;
struct {
int val3;
} subdata;
char *name;
};
int main (int argc, char **argv)
{
struct datastore data = {1, 5, {3}, "a string"};
return data.val2;
}
Current executable set to 'a.out' (x86_64).
(lldb) br se -l 13
Breakpoint created: 1: file ='a.c', line = 13, locations = 1
(lldb) br comm add -s python
Enter your Python command(s). Type 'DONE' to end.
> def printvar_or_children(var):
> if var.GetNumChildren() == 0 and var.IsInScope():
> path = lldb.SBStream()
> var.GetExpressionPath(path)
> print '%s: %s' % (path.GetData(), var.GetValue())
> else:
> for subvar in var:
> printvar_or_children(subvar)
>
> print 'variables visible at breakpoint %s' % bp_loc
> for var in frame.arguments:
> printvar_or_children(var)
> for var in frame.locals:
> printvar_or_children(var)
>
> DONE
(lldb) r
variables visible at breakpoint 1.1: where = a.out`main + 51 at a.c:13, address = 0x0000000100000f33, resolved, hit count = 1
argc: 1
*(*(argv)): '/'
data.val1: 1
data.val2: 5
data.subdata.val3: 3
*(data.name): 'a'
Process 84865 stopped
* thread #1: tid = 0x1f03, 0x0000000100000f33 a.out`main + 51 at a.c:13, stop reason = breakpoint 1.1
frame #0: 0x0000000100000f33 a.out`main + 51 at a.c:13
10 int main (int argc, char **argv)
11 {
12 struct datastore data = {1, 5, {3}, "a string"};
-> 13 return data.val2;
(lldb)
Tip - for sanity's sake I worked on the python over in a side text editor and pasted it into lldb as I experimented.
If you use the frame variable command in lldb to explore your variables at a given stop location, that's the same basic way that you can access them via the SBFrame that is provided to your breakpoint python command in the 'frame' object.
Hope that helps to get you started.
Did you try looking at the python LLDB formatting templates stored in:
XCode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python/lldb/formatters/objc