hglib: show patches for a revision, possible? - python

I'm trying to get the patches for a given revision using hglib. I know the hg command is
hg log -pr rev
but I can't find how to do this or equivalent with hglib. It seems there is not functionality to do that, unless I hack the code myself to run the above command. Any help would be greatly appreciated?

The hglib client.log() interface doesn't support what I wanted to do, but I found a simple way to run an arbitrary hg command. This two lines print the patch of revision rev:
out = client.rawcommand([b'log', b'-pr', b'%i'%rev])
print(str(out, 'utf-8'))

May be this is the actual answer!
import hglib
client = hglib.open(<path>)
client.export (revs = str(<revision number>), output = <output file path>)
You can execute the same with subprocess package by yourself to save interpretation time. Rawcommand just builds a command with the parameters we pass and executes with subprocess again.

Related

Why does subprocess.run create return code 1 even if the command was successful?

From within python, I am trying to check if chocolatey is installed on a windows machine. I used subprocess.run to implement that, however, the return code is 1 even if chocolatey is installed.
Here is my code:
import subprocess
result = subprocess.run(['choco'], capture_output=True, text=True)
print(result.returncode)
Adding options won't change its result. If I test a windows command like dir everything works as expected. Where is my mistake here?
Edited:
As some comments indicated it was not clear what I meant by options, actually I tried similar things as it was suggested already before. However, I was mislead by two things
The idea that a call which I consider to be sucessful would alwas return 0 as code. A good explanation was given by Shine J.
And it turned out that I tried to provide options inline. Instead I had to provide it as a second argument. From the documentation of Popen (which is called underneath) this became clear to me. Chocolatey also returns 0 as return code if called like this:
import subprocess
result = subprocess.run(['choco','-v'], capture_output=True)
print(result.returncode)
However, I believe that Shine J is right in saying that it is better to check if the file is present. Therefore, I will accept this as the correct answer. Thanks!
It totally depends on the value returned by your program with different arguments.
For example, when I run the following on my computer (git is installed):
result = subprocess.run(['git'], capture_output=True)
result.returncode is 1
If I run git with parameter --version like this:
result = subprocess.run(['git','--version'], capture_output=True)
result.returncode is 0
To really check if a program exists or not (on Windows) you could do something like:
try:
result = subprocess.run(['choco'], capture_output=True)
print(result)
except FileNotFoundError:
print("Program not installed")
Check out this official documentation on Subprocess
You ran choco without any arguments, meaning it didn't get a command to perform. It's up to choco whether that's regarded as an error; I suspect it is, much like if you passed it an unknown command. You may want to pass it a command that should succeed, such as choco help.

Iterate commits b/w 2 specified commits in GitPython

import git
repo = git.Repo(repo_dir)
ref_name = 'master'
for commit in repo.iter_commits(rev=ref_name):
<some code here>
This code iterates through all the commits. I want to iterate b/w 2 commits.
Just like git log commit1...commit2
How can I do the same using GitPython's iter_commits() method.
repo.iter_commits(rev='1234abc..5678def') works for me in GitPython==2.1.11
Example:
repo = git.Repo(repo_dir)
for commit in repo.iter_commits(rev='master..HEAD'):
<some code here>
You can use pure gitpython for that.
If you want to able to traverse certain commit (assuming the first
commit is HEAD), just use max_count. See The Commit object
two_commits = list(repo.iter_commits('master', max_count=2))
assert len(two_commits) == 2
if you want similar ability to git log commit1...commit2 as you mentioned:
logs = repo.git.log("--oneline", "f5035ce..f63d26b")
will give you:
>>> logs
'f63d26b Fix urxvt name to match debian repo\n571f449 Add more key for helm-org-rifle\nbea2697 Drop bm package'
You can also use logs = repo.git.log("f5035ce..f63d26b") but it will give you all info (just like you use git log without --oneline)
if you want nice output, use pretty print:
from pprint import pprint as pp
>>> pp(logs)
('f63d26b Fix urxvt name to match debian repo\n'
'571f449 Add more key for helm-org-rifle\n'
'bea2697 Drop bm package')
For more explanation about repo.git.log, see https://stackoverflow.com/a/55545500/6000005
I would suggest you to use PyDriller (a wrapper around GitPython, to make things easier). What you asked can be done like this:
for commit in RepositoryMining("path_to_repo", from_commit="first", to_commit="second").traverse_commits():
# your code
First, make a function to run the git command.
from git import *
from subprocess import Popen, PIPE
def execute_gitcmd(cmd, repo):
pipe = subprocess.Popen(cmd, shell=True, cwd=repo, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, error) = pipe.communicate()
return out, error
pipe.wait()
Then write any git command as you use on terminal, for example:
gitcmd = "git log -n1 --oneline"
Finally, call your function:
log = (execute_gitcmd(gitcmd, your_repository))
Hope this can help.

Odoo - how to use it interactively in python interpreter?

I read here that it might be possible to use python interpreter to access Odoo and test things interactively (https://www.odoo.com/forum/help-1/question/how-to-get-a-python-shell-with-the-odoo-environment-54096), but doing this in terminal:
ipython
import sys
import openerp
sys.argv = ['', '--addons-path=~/my-path/addons', '--xmlrpc-port=8067', '--log-level=debug', '-d test',]
openerp.cli.main()
it starts Odoo server, but I can't write anything in that terminal tab to use it interactively. If for example I write anything like print 'abc', I don't get any output. Am I missing something here?
Sometime I use "logging" library for print output on the console/terminal.
For example:
import logging
logging.info('Here is your message')
logging.warning('Here is your message')
For more details, You may checkout this reference link.
The closest thing I have found to interactive is put the line
import pdb; pdb.set_trace()
in the method I want to inspect, and then trigger that method.
It's clunky, but it works.
As an example, I was just enhancing the OpenChatter implementation for our copy of OpenERP, and during the "figure things out" stage I had that line in .../addons/mail/mail_thread.py::mail_thread.post_message so I could get a better idea of what was happening in that method.
The correct way to do this is with shell:
./odoo-bin shell -d <yourdatabase>
Please, be aware that if you already have an instance of odoo, the port will be busy. In that case, the instance you are opening should be using a different port. So the command should be something like this:
./odoo-bin shell --xmlrpc-port=8888 -d <yourdatabase>
But if you want to have your addons available in the new instance, yo can make something similar to the following:
./odoo-bin shell -c ~/odooshell.conf -d <yourdatabase>
This way you can have in your odooshell.conf whatever you need to have configured (port, addons_path, etc). This way you can work smoothly with your shell.
As I always use docker, this is what I do to have my shell configured in docker:
docker exec -ti <mycontainer> odoo shell -c /etc/odoo/odooshell.conf -d <mydatabase>
You will have the env available to do anything. You can create express python code to make whatever you need. The syntax is very similar to server actions. For example:
partner_ids = env['res.partner'].search([])
for partner in partner_ids:
partner['name'] = partner.name + '.'
env.cr.commit()
Remember to env.cr.commit() if you make any data change.

Using python to check out a file (cleartool)

I'm wondering how to completely automate a checkout. I've tried
os.system('cleartool co ' + pathname)
but that still prompts me to enter a comment about the checkout. Adding more os.system() commands right after doesn't quite work -- they only execute after I've entered the comment.
I'm looking at using subprocess and maybe Popen, but I don't quite understand how they work from the documentation I can find online.
Any help would be much appreciated, thanks!
If you don't need to enter a comment, a simple -nc would be enough:
os.system('cleartool co -nc ' + pathname)
See cleartool checkout man page.
If the comment is known, you can add it directly (-c xxx)
In both cases, the checkout becomes non-interactive, more suite to batch process.
You can use Popen and communicate to enter the comment after calling cleartool:
from subprocess import Popen
p = Popen(['cleartool','co',pathname])
p.communicate("comment\n")

calling pdftotext from python script not working when I change from local machine to my webhosting

I wrote a small python script to parse/extract info from a PDF. I tested it on my local machine, I have python 2.6.2 and pdftotext version 0.12.4.
I am trying to run this on my webhosting server (dreamhost). It has python version 2.5.2 and pdftotext version 3.02.
But when I try to run the script I get the following error at the pdftotext line ( I have checked it with a simple throw away script as well) "Error: Couldn't open file '-'"
def ConvertPDFToText(currentPDF):
pdfData = currentPDF.read()
tf = os.tmpfile()
tf.write(pdfData)
tf.seek(0)
if (len(pdfData) > 0) :
out, err = subprocess.Popen(["pdftotext", "-layout", "-", "-"], stdin = tf, stdout=subprocess.PIPE ).communicate()
return out
else :
return None
Note that I am pass this function the same PDF file and it does have access to it. In another function I can email myself the PDF document from the same script running on the webhost.
What am I doing wrong? What is the possible difference in usage for subprocess/python/pdftext between my local version and the webhost version? I am guessing I will have to modify the command, so any help would be greatly appreciated.
Thanks in advance.
The hint for the answer lay in Noufal's comment, to use the filename. But the os.tmpfile() doesn't have a filename. I had to use another module. The modified code is given below.
#import tempfile
def ConvertPDFToText(currentPDF):
pdfData = currentPDF.read()
tf = tempfile.NamedTemporaryFile()
tf.write(pdfData)
tf.seek(0)
outputTf = tempfile.NamedTemporaryFile()
if (len(pdfData) > 0) :
out, err = subprocess.Popen(["pdftotext", "-layout", tf.name, outputTf.name ]).communicate()
return outputTf.read()
else :
return None
I am not sure sure how to give Noufal's comment the points for this answer though. Perhaps he can cut and paste this answer?
Can the pdftotext read from the command line directly on webhost? Can you verify this? Also, why don't you pass the name of the temporary file as an argument rather than give it on standard input? (repasting here as per your suggestion).
If you have shell access to the server, try to run without Python:
# pdftotext -layout - -
and:
# pdftotext -layout
Some versions of pdftotext may use stdi/stdout then run without any files in command line. Try
out, err = subprocess.Popen(["pdftotext", "-layout"], stdin = tf, stdout=subprocess.PIPE ).communicate()
Or use temp file as suggested by Noufal Ibrahim.

Categories

Resources