Add confirmation step to custom Django management/manage.py command - python

I created the following custom management command following this tutorial.
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from topspots.models import Notification
class Command(BaseCommand):
help = 'Sends message to all users'
def add_arguments(self, parser):
parser.add_argument('message', nargs='?')
def handle(self, *args, **options):
message = options['message']
users = User.objects.all()
for user in users:
Notification.objects.create(message=message, recipient=user)
self.stdout.write(
self.style.SUCCESS(
'Message:\n\n%s\n\nsent to %d users' % (message, len(users))
)
)
It works exactly as I want it to, but I would like to add a confirmation step so that before the for user in users: loop you are asked if you really want to send message X to N users, and the command is aborted if you choose "no".
I assume this can be easily done because it happens with some of the built-in management commands, but it doesn't seem to cover this in the tutorial and even after some searching and looking at the source for the built-in management commands, I have not been able to figure it out on my own.

You can use Python's raw_input/input function. Here's an example method from Django's source code:
from django.utils.six.moves import input
def boolean_input(question, default=None):
result = input("%s " % question)
if not result and default is not None:
return default
while len(result) < 1 or result[0].lower() not in "yn":
result = input("Please answer yes or no: ")
return result[0].lower() == "y"
Be sure to use the import from django.utils.six.moves if your code should be compatible with Python 2 and 3, or use raw_input() if you're on Python 2. input() on Python 2 will evaluate the input rather than converting it to a string.

Related

How to read custom message type using ros2bag

So I have this code which works great for reading messages out of predefined topics and printing it to screen. The rosbags come with a rosbag_name.db3 (sqlite) database and metadata.yaml file
from rosbags.rosbag2 import Reader as ROS2Reader
import sqlite3
from rosbags.serde import deserialize_cdr
import matplotlib.pyplot as plt
import os
import collections
import argparse
parser = argparse.ArgumentParser(description='Extract images from rosbag.')
# input will be the folder containing the .db3 and metadata.yml file
parser.add_argument('--input','-i',type=str, help='rosbag input location')
# run with python filename.py -i rosbag_dir/
args = parser.parse_args()
rosbag_dir = args.input
topic = "/topic/name"
frame_counter = 0
with ROS2Reader(rosbag_dir) as ros2_reader:
ros2_conns = [x for x in ros2_reader.connections]
# This prints a list of all topic names for sanity
print([x.topic for x in ros2_conns])
ros2_messages = ros2_reader.messages(connections=ros2_conns)
for m, msg in enumerate(ros2_messages):
(connection, timestamp, rawdata) = msg
if (connection.topic == topic):
print(connection.topic) # shows topic
print(connection.msgtype) # shows message type
print(type(connection.msgtype)) # shows it's of type string
# TODO
# this is where things crash when it's a custom message type
data = deserialize_cdr(rawdata, connection.msgtype)
print(data)
The issue is that I can't seem to figure out how to read in custom message types. deserialize_cdr takes a string for the message type field, but it's not clear to me how to replace this with a path or how to otherwise pass in a custom message.
Thanks
One approach would be that you declare and register it to the type system as a string:
from rosbags.typesys import get_types_from_msg, register_types
MY_CUSTOM_MSG = """
std_msgs/Header header
string foo
"""
register_types(get_types_from_msg(
MY_CUSTOM_MSG, 'my_custom_msgs/msg/MyCustomMsg'))
from rosbags.typesys.types import my_custom_msgs__msg__MyCustomMsg as MyCustomMsg
Next, using:
msg_type = MyCustomMsg.__msgtype__
you can get the message type that you can pass to deserialize_cdr.
Also, see here for a quick example.
Another approach is to directly load it from the message definition.
Essentially, you would need to read the message
from pathlib import Path
custom_msg_path = Path('/path/to/my_custom_msgs/msg/MyCustomMsg.msg')
msg_def = custom_msg_path.read_text(encoding='utf-8')
and then follow the same steps as above starting with get_types_from_msg().
A more detailed example of this approach is given here.

Executing custom management commands return None

I am trying to create custom management command which will execute data from Api. I wrote this code:
from django.core.management.base import BaseCommand, CommandError
from data.models import Country
import requests
import json
def extracting():
country_req = requests.get("https://api-football-v1.p.rapidapi.com/countries", headers = {"X-RapidAPI-Key": "my_token"})
parsed_string = json.loads(country_req.text)
class Command(BaseCommand):
def handle(self, **options):
print(extracting())
but, when I try to execute it with python manage.py extract in my console I see None, while when I try to run this code in console without custom management command I see data which I try to execute.
Any ideas?
You do not return anything from the extracting() method. Depending on your interactive console, you might see the values for variables. But what you probably want to do is:
def extracting():
country_req = requests.get("https://api-football-v1.p.rapidapi.com/countries", headers = {"X-RapidAPI-Key": "my_token"})
return json.loads(country_req.text)

Use input variables across Python scripts

I'm trying to access variables that are contained in functions after an operation is performed in another Python script, but I don't want to run through the operations of the function, I just need access to the returned value of the variables gh and user.
I've tried different ways to do this such as setting the initial value of the variable to None in the main script, but the problem I run into is when I do an import of script1 into script2, it runs through the script and resets the variable in question to None again. In addition, I've tried to wrap them in a class with no luck.
Also, I've tried using if __name__ = '__main__': to run the functions, but I can't seem to figure out how to get the values out of the functions into script2 to use as global variables.
I've seen some answers here that may work such as returning the values of the function to another function for use??, but I I can't quite nail the syntax as the function doesn't seem to hold the value of the variable.
If I have asked this question incorrectly, please let me know how to improve it as I'm trying to ask "good" questions so I don't get banned. I'm still learning and I do ask a lot of questions here, but I've learned a lot by doing so.
script1.py:
#! /usr/bin/python
import github3
from github3 import login, GitHub, authorize
from getpass import getuser, getpass
import requests
import configparser
def getCreds():
try:
user = input('GitHub username: ')
except KeyboardInterrupt:
user = getuser()
password = getpass('GitHub token for {0}: '.format(user))
gh = login(user, password)
if __name__ == '__main__':
getCreds()
exec(open("next_file.py").read())
script2.py
import os
import github3
from github3 import login, GitHub, authorize
from getpass import getuser, getpass
import requests
import csv
import configparser
import sys
import script1
import codecs
gh = script1.gh
user = script1.user
def one_commit_one_file_change_pr():
#open csv file and create header rows
with open('c:\\commit_filechange.csv', 'w+') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(['Login', 'Title', 'Commits', 'Changed Files','Deletions', 'Additions'])
for pr in result:
data = pr.as_dict()
changes = (gh.repository(user, repo).pull_request(data['number'])).as_dict()
if changes['commits'] == 1 and changes['changed_files'] == 1:
#keep print to console statement for testing purposes
#print changes['user']['login']
with open('c:\\commit_filechange.csv', 'a+') as f:
csv_writer = csv.writer(f)
csv_writer.writerow([changes['user']['login'], changes['title'], changes['commits'], changes['changed_files']])
one_commit_one_file_change_pr()
Here is a solution which I believe is common practice. Set up a file called global_var.py (or something like it) and store global variables there. (See this post by #systemizer) Here is a simplified version of what will work with your code:
script1.py
if __name__=='__main__':
user = raw_input('GitHub username: ')
with open('global_var.py','w') as f:
f.write("user = '%s'" % user)
password = 'blah'
gh = '<login(user, password)>'
script2.py
from script1 import gh
from global_var import user
print user
print gh
This answer is purely based on my assumption that you want get the user credentials only once and want to re-use it "n" number of times later in other scripts.
Here is how I would do it ,
Update1
Your problem also has to do with how you want to organize and run your scripts, the below examples work if you have bundled your scripts in to python package and run them
For. eg
but if you are planning to run individual scripts separately , then you have no other option but to invoke the login prompt for each script unless you plan to completely remove asking for user credentials and use the pre-configured data from a file.
script1
from github3 import login
USER_CREDS = None # Store raw input credentials here ,not recomended
GIT_USERS = {} # global dict to store multiple users with username as key
def getCredentials():
global USER_CREDS
if USER_CREDS:
print "returning user credentials"
return USER_CREDS
print "gettting user credentials"
user = raw_input("Enter Username")
pwd = raw_input("Enter Password")
USER_CREDS = (user, pwd)
return USER_CREDS
def do_login():
global GIT_USERS
user, pwd = getCredentials()
if not GIT_USERS.get(user, None):
gh = login(user, password=pwd)
GIT_USERS[user] = gh
return GIT_USERS[user]
in other scripts
from script1 import do_login
# the first time do_login() is called it asks for user credentials
print do_login()
# the next times it just returns the previously collected one
print do_login()
Example 2
script 3
from script1 import do_login
creds = do_login()
script 4
from script3 import creds
from script1 import do_login
print creds
print do_login() # No input prompt would be provided

How to trigger a python script on the django server for the particular form input?

i want to make a search box on my website. I want the output of the particular searchbox input to be generated by particular file which is mapped on the server for the given output.
for ex:- fib 10
will run fib.py and give the response will be the result of the fib.py
You could use subprocess module to run command and take the output.
Update 1
Example view:
import subprocess
def runCmd(request):
cmd = request.POST.get('cmd')
param = request.POST.get('param')
codeDir = '/path/to/py/file/'
absoluteCodePath = codeDir + cmd + '.py'
result = subprocess.check_output([absoluteCodePath, param])
return result
Why would you want to do that? Just import your file/module and use it, this is the correct way.
Lets say you have this code in fib.py:
def calculate(.....):
#code. ...
return result
Now in you other file, lets say it's views.py just do:
import fib
# this is the search view
def search(request):
if request.method == "POST":
# other code
fib.calculate(param) # where param is the value of the search field
I'm not sure if I understood you correctly.. but no there's no reason to use subprocess and execute a file and get the value returned...

Determine if current user is in Administrators group (Windows/Python)

I want certain functions in my application to only be accessible if the current user is an administrator.
How can I determine if the current user is in the local Administrators group using Python on Windows?
You could try this:
import ctypes
print ctypes.windll.shell32.IsUserAnAdmin()
import win32net
def if_user_in_group(group, member):
members = win32net.NetLocalGroupGetMembers(None, group, 1)
return member.lower() in list(map(lambda d: d['name'].lower(), members[0]))
# Function usage
print(if_user_in_group('SOME_GROUP', 'SOME_USER'))
Of course in your case 'SOME_GROUP' will be 'administrators'
I'd like to give some credit to Vlad Bezden, becuase without his use of the win32net module this answer here would not exist.
If you really want to know if the user has the ability to act as an admin past UAC you can do the following. It also lists the groups the current user is in, if needed. It will work on most (all?) language set-ups. The local group just hast to start with "Admin", which it usually does... (Does anyone know if some set-ups will be different?)
To use this code snippet you'll need to have pywin32 module installed,
if you don't have it yet you can get it from PyPI: pip install pywin32
IMPORTANT TO KNOW:
It may be important to some users / coders that the function os.getlogin() is only available since python3.1 on Windows operating systems...
python3.1 Documentation
win32net Reference
from time import sleep
import os
import win32net
if 'logonserver' in os.environ:
server = os.environ['logonserver'][2:]
else:
server = None
def if_user_is_admin(Server):
groups = win32net.NetUserGetLocalGroups(Server, os.getlogin())
isadmin = False
for group in groups:
if group.lower().startswith('admin'):
isadmin = True
return isadmin, groups
# Function usage
is_admin, groups = if_user_is_admin(server)
# Result handeling
if is_admin == True:
print('You are a admin user!')
else:
print('You are not an admin user.')
print('You are in the following groups:')
for group in groups:
print(group)
sleep(10)
# (C) 2018 DelphiGeekGuy#Stack Overflow
# Don't hesitate to credit the author if you plan to use this snippet for production.
Oh and WHERE from time import sleep and sleep(10):
INSERT own imports/code...

Categories