gitpython: How to show diffs between blobs in a human readable format, as in gitk? - gitpython

I must be missing something really basic. Given this script:
import git
repo = git.Repo(r'C:/leo.repo/leo-editor')
diff_index = repo.head.commit.diff('HEAD~1')
for d in diff_index:
print('%s %9s %9s %s' % (
d.change_type, id(d.a_blob), id(d.b_blob), d.a_path))
I get something like this:
M 173600704 173600080 leo/core/commit_timestamp.json
M 173600368 173599408 leo/core/leoTest.py
M 173600272 173598928 leo/test/unitTest.leo
So far, so good. This is compatible with what gitk shows, that is, modifications to the three files shown.
But now, having access to the a_blob and b_blob objects for each file, how do I get a human-readable diff of the differences between those two blobs? In other words, I want to recreate what gitk shows.
I don't see anything in the docs related to this.
Edward

My question is a variant of this stack-overflow question.
given a blob, blob.data_stream.read() returns its raw contents, that is a <str> object on Python 2, and a <bytes> object on Python 3.
Rather than reading the feeble api docs for Objects.Blob, one would be better off reading the source code. Indeed, Objects.Blob is a subclass of base.IndexObject, which in turn inherits the data_stream property from base.Object (not to be confused with object).

Related

DMQL2 Query Syntax for PHRets v2 Seach() to include filter arguments?

(It's been a while since I've been here.)
I've been using the first version of PHRets v1 for years, and understood it well enough to get by, but now I'm trying to understand the advantages of v2.6.2. I've got it all installed and the basics are working fine. My issues are pretty much with comprehending fine points of query syntax that goes into the rets=>Search() statement. (I'm much more familiar with SQL statements). Specifically, I'd like to have a query return a list of properties, EXCLUDING those which already have the status of "Sold".
Here's where I am stuck: If I start with this
`$results = $rets->Search('Property', 'A','*',['Select' => 'LIST_8,LIST_105,LIST_15,LIST_19,listing_office_shortid']);`
That works well enough. BUT I'd like to fit in a filter like:
"LIST_15 != Sold", or "NOT LIST_15=Sold"...something like that. I don't get how to fit/type that into a PHRets Search().
I like PHRets but it is so hard to find well-organized/complete documentation about specific things like this. Thanks in advance.
As in my comment above I've figured out that the filter goes in the third argument position ('*', as in the original question). The tricky thing was having to find a specific "sold" code for each class of properties and placing it in that position like so: '(LIST_15=~B4ZIT1Y75TZ)', (notice the =~ combination of characters that means "does not equal" in this context). I've found the code strings for each of the property types (not clear WHY they would need to be unique for each type of property: "Sold" is Sold for any type, after all) but the correct code for a single-family residential property (type 'A' ...at least for the MLS in which I have to search is:
$results = $rets->Search('Property', 'A','(LIST_15=~B4ZIT1Y75TZ)',['Select' => 'LIST_8,LIST_105,LIST_15,LIST_19,listing_office_shortid']);
(again, the code to go with LIST_15 will be different for the different types of properties.) I think there is a better answer that involves more naturalistic language, but this works and I guess I will have to be satisfied with it for now. I hope this is of some use to anyone else struggling with this stuff.

Change the way an object is displayed in debugger/inspector variable-value table

I would like to know if there is a message I can override in Pharo so that my custom classes display more descriptive information in the inspector/debuger much like simple variable types do, like Integers or Strings. For instance:
Instead of that, I would like it to show a more custom and informative description consisting of its internal variales so as to have a tighter/tidier view of the variables instead of having to click on it and open another chart (therefore losing sight of the information on the previous chart). I know you can increase the amount of charts shown below, but that is not the point of the question. I would like to achieve something like this:
I have browsed the pharo forums and found nothing, I have also tried overriding over 30 methods hoping that one of them changed the output. Only the class message seemed to change the output, but I could only return an instance of Metaclass and besides messing with this message would break a lot of stuff. Finally I tried to reverse engineer the debugger and then the inspector to see at which point is the table constructed and what values are used or which messages are sent to build said values, but it was just too much for me, the callstack kept growing and I couldn't even scratch the surface.
Luckily, doing this in any Smalltalk is very easy. Types inherited from Object are expected to answer to the message printString, and ultimately printOn: aStream. Those messages are expected to give a description of the object. So, you should just override printOn: in your class (printString uses printOn:) and all the browsers and inspectors will automatically use it. There other possibilities in Pharo, if you want to provide more complex information in different tabs, but I think printOn: will suffice for you.
An example would be:
MyPoint>>printOn: aStream
aStream nextPut: ${.
x printOn: aStream.
aStream nextPutAll: ', '
y printOn: aStream.
aStream nextPut: $}
In Smalltalk, every time you observe something you don't like or understand, you ask the question: Which message is doing this?
In your case, the question would be: Which message creates the string a MyPoint that I see everywhere?
Next, to answer your question you need to find a good place for inserting a halt and then debug from there until you find the culprit. To do this just find the simplest expression that would reproduce the issue and debug it. In your case the right-click command in the Playground will do. So,
Write and select (MyPoint on: 14 and: -5) halt in a Playground.
Right-click and issue the Print it command (I'm assuming you already checked that this command produces the string 'a MyPoint').
Debug
Go over the evaluation of #DoIt, which answers the result
Continue this way alternating between Into and Over to make sure you follow the result to where it's being taken
Eventually you will reach the implementation of Object >> #printString. Bingo!
Now you can open a System Browser and take a look at this method, study how it's been implemented in different classes, etc. Your investigation should show you that the most basic message for printing is #printOn:. You may also want to take a look at other implementors so to better understand what people usually do. (Bear in mind that writing good #printOn:s is a minimalist art)
Overriding printOn: will work for simple cases where you want to just change description.
Pharo allows a lot more than that!
Due the extensible (moldable) nature of our inspector, you do not need to override a method to get your own visualisation of the object.
For example, look this array visualisation:
This is obtained adding this method to Collection:
gtInspectorItemsIn: composite
<gtInspectorPresentationOrder: 0>
^ composite fastList
title: 'Items';
display: [ self asOrderedCollection ];
beMultiple;
format: [ :each | GTObjectPrinter asTruncatedTextFrom: each ];
send: [ :result |
result
ifNil: [ nil ]
ifNotNil: [ result size = 1
ifTrue: [ result anyOne ]
ifFalse: [ self species withAll: result ]
]
]
if you browse for senders of gtInspectorPresentationOrder: you will see there are already a lot of special visualisations in the image.
You can take those as an example on how to create your own, adapted exactly to what you need :)

Primitive type as data structure for API Blueprint

I want to use primitive type for describe data structure. Like so:
# Data Structures
## Video Delete (enum[number])
+ `0` - Successful deletion.
+ `1` - Error occured.
And the output is.
{
"enum": [
1,
0
],
"$schema": "http://json-schema.org/draft-04/schema#"
}
So description is missing. I've tried to put description in different places. I did a lot of things (do not wanna talk about them). Also I've tried to add info to enum values like so:
+ `0` (number) - Successful deletion.
I do not know whether this problem deals with MSON syntax or Aglio generator.
The syntax above is supported by MSON as far as I can tell. The problem is that Aglio doesn't do anything with the description, and when I went to look into adding it I realized that it isn't really supported in JSON Schema. There seem to be two methods people use to get around that fact:
Add the enumerated value descriptions to the main description, the Olio theme 1.6.2 has support for this but the C++ parser seems to still have some bugs around this feature:
## Video Delete (enum[number]) - 0 for success, 1 for error
Use a weird oneOf syntax where you create sets of single enums with a description. I don't recommend this.
Unfortunately the first option requires work on your part and can't easily be done in Aglio. Does anyone else have a better description and some samples of MSON input -> JSON Schema output?

Montage using PythonMagick in Python 3?

I was hoping to be able to generate montages using PythonMagick. The documentation seems very sparse, but I've been trying to hunt it down using the code completion part of Eclipse at least, as well as a few other questions' suggestions here on Stack Overflow. It seems that the MagickWand API has the function I am looking for, according to this:
http://www.imagemagick.org/api/MagickWand/montage_8c.html
However, I cannot seem to find it in PythonMagick. Is this simply unavailable? If so I might just ditch the rest of my PythonMagick code and rely on subprocess.call on a portable ImageMagick distribution or something like that (this program will have to be portable, and run on Windows with an easy port to Mac OS... so far I have a few other PythonMagick commands working so I'd like to keep this route going if possible).
Thanks!
Using the python imagemagick/graphicsmagick bindings helps a lot, but unfortunately not all of the functionality is there yet. I actually had the same problem with #FizxMike. I needed to use montage and then do some further operations, but saving the file on hard disk and then reloading it in a proper pgmagick object in order to do the rest of the operations and saving it again was slow.
Eventually I used the subprocess solution, but instead of saving in a file, I redirect the output in stdout. Then, I use the stdout to load the image from a pgmagick.Blob in a pgmagick.Image object and do the rest of the processing in python code.
The procedure looks like this in code:
import os
import pgmagick
import subprocess
my_files = []
# Dir with the images that you want to operate on
dir_with_images = "."
for file in os.listdir(dir_with_images):
if file.endswith(".png"):
my_files.append(os.path.join(dir_with_images, file))
montage_cmd = ['gm', 'montage']
montage_cmd.extend(my_files)
# The trick is in the next line of code. Instead of saving in a file, e.g. myimage.png
# the montaged file will just be "printed" in the stdout with 'png:-'
montage_cmd.extend(['-tile', '2x2', '-background', 'none', '-geometry', '+0+0', 'png:-'])
# Use the command line 'gm montage' since there are not python bindings for it :(
p = subprocess.Popen(montage_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Get the stdout in a variable
stdout, stderr = p.communicate()
# Load the stdout in a python pgmagick Image object using the pgmagick.Blob
# and do the rest of the editing on python code
img = pgmagick.Image(pgmagick.Blob(stdout))
# Display the image
img.display()
geometry = pgmagick.Geometry(300, 200)
geometry.aspect(True)
# Resize the montaged image to 300x200, but keep the aspect ratio
img.scale(geometry)
# Display it again
img.display()
# And finally save it <- Only once disk access at this point.
img.write('myimage.png')
I have the same problem, even pgmagick lacks the montageImage() function needed (Magick++ montage example)
This is what I do (in a Django View):
#ImageMagick CLI is better documented anyway (-background none preserves transparency)
subprocess.call("montage -border 0 -geometry "+str(cols)+"x -tile 1x"+str(len(pages))+" "+target_path[0:len(target_path)-4]+"[0-9]*.png -background none "+target_path,shell=True)`
Not fun because I have to juggle around a bunch of files first... writing to hard disk is not the fastest thing to do, then delete the temp files.
I would much rather do it all in ram.
I am still in search of a better answer myself.

Pass data from workspace to a function

I created a GUI and used uiimport to import a dataset into matlab workspace, I would like to pass this imported data to another function in matlab...How do I pass this imported dataset into another function....I tried doing diz...but it couldnt pick diz....it doesnt pick the data on the matlab workspace....any ideas??
[file_input, pathname] = uigetfile( ...
{'*.txt', 'Text (*.txt)'; ...
'*.xls', 'Excel (*.xls)'; ...
'*.*', 'All Files (*.*)'}, ...
'Select files');
uiimport(file_input);
M = dlmread(file_input);
X = freed(M);
I think that you need to assign the result of this statement:
uiimport(file_input);
to a variable, like this
dataset = uiimport(file_input);
and then pass that to your next function:
M = dlmread(dataset);
This is a very basic feature of Matlab, which suggests to me that you would find it valuable to read some of the on-line help and some of the documentation for Matlab. When you've done that you'll probably find neater and quicker ways of doing this.
EDIT: Well, #Tim, if all else fails RTFM. So I did, and my previous answer is incorrect. What you need to pass to dlmread is the name of the file to read. So, you either use uiimport or dlmread to read the file, but not both. Which one you use depends on what you are trying to do and on the format of the input file. So, go RTFM and I'll do the same. If you are still having trouble, update your question and provide details of the contents of the file.
In your script you have three ways to read the file. Choose one on them depending on your file format. But first I would combine file name with the path:
file_input = fullfile(pathname,file_input);
I wouldn't use UIIMPORT in a script, since user can change way to read the data, and variable name depends on file name and user.
With DLMREAD you can only read numerical data from the file. You can also skip some number of rows or columns with
M = dlmread(file_input,'\t',1,1);
skipping the first row and one column on the left.
Or you can define a range in kind of Excel style. See the DLMREAD documentation for more details.
The filename you pass to DLMREAD must be a string. Don't pass a file handle or any data. You will get "Filename must be a string", if it's not a string. Easy.
FREAD reads data from a binary file. See the documentation if you really have to do it.
There are many other functions to read the data from file. If you still have problems, show us an example of your file format, so we can suggest the best way to read it.

Resources