I have Windows 10 and I use Git Bash. I want to write a python git hook to prepend a string to commit messages if the user so wishes.
However the input function of Python (3.x) seems to fail because the standard input in this context somehow sends an EOF directly instead of my keystrokes or something :
$ g commit -m "Content v4"
Do you wish to prepend <some_string> to your commit message ? [y/n/a[bort]] : Traceback (most recent call last):
File ".git/hooks/prepare-commit-msg", line 12, in <module>
response = input("Do you wish to prepend <some_string> to your commit message ? [y/n/a[bort]] : ")
EOFError: EOF when reading a line
Here the content of my prepare-commit-msg-hook :
#!/usr/bin/env python
import sys, re
from subprocess import check_output
commit_msg_filepath = sys.argv[1]
invalid_response = True
while invalid_response:
response = raw_input("Do you wish to prepend <some_string> to your commit message ? [y/n/a[bort]] : ")
print("You responded : "+response)
if response == 'y':
invalid_response = False
issue = "<some_string>"
with open(commit_msg_filepath, 'r+') as fh:
commit_msg = fh.read()
fh.seek(0, 0)
fh.write('[%s] %s' % (issue, commit_msg))
elif response == 'n':
invalid_response = False
# Do nothing
elif response == 'a':
invalid_response = False
print("Aborting (clearing commit message)")
# Erase commit message contents to abort commit.
with open(commit_msg_filepath, 'w'):
pass
else:
invalid_response = True
This script works as expected when run from git bash directly. :
user#computer MINGW64 /c/workset_git/playground (master)
$ python .git/hooks/prepare-commit-msg file
Do you wish to prepend artf58197 to your commit message ? [y/n/a[bort]] : y
You responded : y
user#computer MINGW64 /c/workset_git/playground (master)
$ python .git/hooks/prepare-commit-msg file
Do you wish to prepend artf58197 to your commit message ? [y/n/a[bort]] : n
You responded : n
user#computer MINGW64 /c/workset_git/playground (master)
$ python .git/hooks/prepare-commit-msg file
Do you wish to prepend artf58197 to your commit message ? [y/n/a[bort]] : a
You responded : a
Aborting (clearing commit message)
The contents of file are edited as desired.
How can I solve this ? I am willing to change scripting language if needed, and if someone provides a translation.
Thanks !
EDIT : This smells. It seems it's hard or downright impossible.
How do I prompt the user from within a commit-msg hook?
which has a link to this
https://public-inbox.org/git/pull.790.git.1605625363309.gitgitgadget#gmail.com/T/#u
Git Hook - Ruby Code - Interactive Input
This was originally about some Ruby code, but the answer given was generically negative about the attempt.
Related
I am having problems with a simple program I wrote but do not know where the problem is, and it is giving me a Syntax error.
This is my code:
username = {}
temp = True
while temp:
name = input("Please input your username: ")
response = input("What is the place you want to visit? ")
username[name] = response
end = input("Do you want to end the program? Yes/No ")
if end == 'Yes':
temp = False
print("These are the results of the poll: ")
for names, responses in username.items():
print(names + " wants to go to " + responses)
This is my error:
File "<stdin>", line 1
/usr/local/bin/python3 "/Users/eric/Python Notes/Notes.py"
^
SyntaxError: invalid syntax
Check out the accepted answer here:
syntax error when using command line in python
Looks like your problem is that you are trying to run python test.py from within the Python interpreter, which is why you're seeing that traceback.
Make sure you're out of the interpreter, then run the python test.py command from bash or command prompt or whatever.
There are also some VSCode-specific tips here:
Invalid Syntax error when running python from inside Visual Studio Code
I am trying to write a post-installation script using Python and Bash, and I am having trouble with defining functions. Below is the main file of the program:
#!/usr/bin/env python3
import variables
# Main program loop
while True:
userResponse = str.lower(input('''What would you like to do?
f: Starts the full post-install setup
u: Starts configuring users
p: Starts the packages setup
s: Starts the systemctl setup
c: Starts the configs setup
q: Terminates the program\n'''))
if userResponse == 'f':
print('Starting full post-install setup...')
variables.fullSetup()
elif userResponse == 'u':
variables.configureUsers()
elif userResponse == 'p':
variables.installEssentialPackages()
elif userResponse == 's':
variables.configureSystemctl()
elif userResponse == 'c':
variables.configureSystem()
elif userResponse == 'q':
print('Terminating program...')
quit()
else:
print('Input not recognized.')
And here is the variables file:
import subprocess
def configureUsers():
print('Attempting to configure system users...')
subprocess.run(
'./post_install_scripts/01_users.sh',
shell = True)
def installEssentialPackages():
print('Attempting to install essential packages...')
subprocess.run(
'./post_install_scripts/02_pkgs.sh',
shell = True)
def configureSystemctl():
print('Attempting to configure systemctl...')
subprocess.run(
'./post_install_scripts/03_systemctl.sh',
shell = True)
def configureSystem():
print('Attempting to configure system...')
subprocess.run(
'./post_install_scripts/04_configs.sh',
shell = True)
def fullSetup():
print('Attempting to run a full setup...')
configureUsers()
installEssentialPackages()
configureSystemctl()
configureSystem()
On line #19, I am getting the following error:
"fullSetup" is not a known member of a module
I don't understand what I am doing wrong right here. All seems good to me. If you would like to see the entire repo on Github, you can follow this link to see the entire repo and its contents.
Hopefully someone here can help me out.
Extra Info
I am using Arch Linux
I have the latest Python version
I am using Neovim as my editor, and you can find its dotfiles here.
How are you trying to run this? I just cloned your repo and ran:
python3 setup.py
and I get this:
What would you like to do?
f: Starts the full post-install setup
u: Starts configuring users
p: Starts the packages setup
s: Starts the systemctl setup
c: Starts the configs setup
q: Terminates the program
This is using Python 3.7.
I should further clarify, are you seeing this error when you run the code, or just from some type checker like mypy?
I am able to write a script to checkout the code from SVN issue using "pysvn" module but just wanted to know is there any way I can do without pysvn also ? Because pysvn is third party library which I have to install separately on linux and windows both which I don't want. Please help me get alternate way in which I don't have to install any third party module code -
import pysvn,os,shutil
def getLogin(realm, username, may_save):
svn_user = '<my-username>'
svn_pass = '<my-password>'
return True, svn_user, svn_pass, False
def ssl_server_trust_prompt( trust_dict ):
return (True # server is trusted
,trust_dict["failures"]
,True) # save the answer so that the callback is not called again
def checkOut(svn_url,dest_dir):
if os.path.isdir(dest_dir):
shutil.rmtree(dest_dir)
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
else:
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','ABC')
print "checked out the code \n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','XYZ')
print "checked out the code\n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','MNP')
print "checked out the code \n”
You can pass username and password as arguments:
$ svn update --username 'user2' --password 'password'
You can make Executable of ur script which will include the pysvn into binary file, thus wouldn't need to import or pip install any library, n ur code will run on python-less machines too
I have pexpect working, but I am having problems printing the output back from it. In my test script below, it creates the ssh connection, and then sends a sudo su -, then my password, and then sends a line that would require sudo access to do (I have also added p.interact() a few times to make sure it is at root). The problem I am having, is with returning the output of the commands I run. In the end I am wanting to run some top commands, and some du -h, and other(much more complex) space commands. But currently when it tries to print p.before, I get:
Traceback (most recent call last):
File "./ssh.py", line 37, in <module>
print p.before()
TypeError: 'str' object is not callable
Here is the script I am working from(edited to remove my pass and such)
#!/usr/bin/env python
import pexpect
import struct, fcntl, os, sys, signal
def sigwinch_passthrough (sig, data):
# Check for buggy platforms (see pexpect.setwinsize()).
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912 # assume
s = struct.pack ("HHHH", 0, 0, 0, 0)
a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
global global_pexpect_instance
global_pexpect_instance.setwinsize(a[0],a[1])
ssh_newkey = 'Are you sure you want to continue connecting'
p=pexpect.spawn('ssh user#localhost')
i=p.expect([ssh_newkey,'password:',pexpect.EOF,pexpect.TIMEOUT],1)
if i==0:
print "I say yes"
p.sendline('yes')
i=p.expect([ssh_newkey,'password:',pexpect.EOF])
if i==1:
print "I give password",
p.sendline("mypassword")
elif i==2:
print "I either got key or connection timeout"
pass
elif i==3: #timeout
pass
global global_pexpect_instance
global_pexpect_instance = p
p.sendline("sudo su -")
p.sendline("mypasswd")
p.sendline("mkdir /home/user/test")
print p.before
I am working off of this link: http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/
Any help is much appreciated.
EDIT: As Armin Rigo pointed out below. I was calling to p.before as a function like p.before(). Stupid mistake on my part, as this explains why I was getting this error today, and not yesterday when I was trying this. After making that change to my script, and modifying the command being sent, print p.before, and no output is returned. Any other ways to return output from a sendline() command?
Use logfile, that logfile is store all output in terminal.use that example code:-
child = pexpect.spawn("ssh user#localhost")
child.logfile = open("/tmp/mylog", "w")
child.expect(".*assword:")
child.send("guest\r")
child.expect(".*\$ ")
child.sendline("python -V\r")
open the log file and see everything in terminals event
To fetch the complete output after sendline use child.read()
e.g.
cmd_resp = pexpect.spawnu(cmd) # for execution of the command
str_to_search = 'Please Enter The Password'
cmd_resp.sendline('yes') # for sending the input 'yes'
resp = cmd_resp.expect([str_to_search, 'password:', EOF], timeout=30) # fetch the output status
if resp == 1:
cmd_resp.sendline(password)
resp = cmd_resp.expect([str_to_search, 'outputString:', EOF], timeout=30)
print(cmd_resp.read()) # to fetch the complete output log
p.before is a string - not a function. To see the output you have to write
print p.before.
Hope this might help you
Based on Chapter 12 of the OTP in Action book and Cesarini's book I wrote this Erlang code:
Erlang:
p(Param) ->
?DBG("Starting~n", []),
Cmd = "python test.py",
Port = open_port({spawn,Cmd}, [stream,{line, 1024}, exit_status]),
?DBG("Opened the port: ~w~n", [Port]),
Payload = term_to_binary(list_to_binary(integer_to_list(Param))),
erlang:port_command(Port, Payload),
?DBG("Sent command to port: ~w~n", [Payload]),
?DBG("Ready to receive results for command: ~w~n", [Payload]),
receive
{Port, {data, Data}} ->
?DBG("Received data: ~w~n", [Data]),
{result, Text} = binary_to_term(Data),
Blah = binary_to_list(Text),
io:format("~p~n", [Blah]);
Other ->
io:format("Unexpected data: ~p~n", [Other])
end.
Python:
import sys
def main():
while True:
line = sys.stdin.readline().strip()
if line == "stop-good":
return 0
elif line == "stop-bad":
return 1
sys.stdout.write("Python got ")
sys.stdout.write(line)
sys.stdout.write("\n")
sys.stdout.flush()
if __name__ == "__main__":
sys.exit(main())
The Erlang code suspends at the recieve clause - it never gets any message.
I have also checked Python from a regular Linux shell - it prints out every user input (1 - "Python got 1").
Where is the mistake here? Why doesn't my Erlang code get anything back?
There are two points:
make sure that Python does not buffer your output, try running python -u in open_port
using term_to_binary/1 and binary_to_term/1 won't work, since they assume that Python is able to encode/decode Erlang External Term Format, which does not seem to be the case. If you want to go this route, check out ErlPort
Does your Param contain the command limiter for Python? (in this case I assume newline, "\n"). Also, list_to_binary/1 and then a term_to_binary/1 feels kinda wrong. term_to_binary/1 directly (including the newline) should be sufficient.