I'm trying to write an R package with a function to send emails using python's smtplib module. The function works when I source it directly or with devtools::load_all(), but crashes R when I library my package and call the function.
I was using the mailR package, which uses java to send emails but I'm having issues after upgrading the version of java. I decided to write a quick package to replace it with a python version. Everything worked as expected until I installed it with devtools::install_local() and then tried calling the function. I've not got much experience with python, I feel like it might have something to do with how I'm importing the python modules, I tried moving the imports inside the function but that didn't help.
This is the python function that I'm sourcing with reticulate:
import smtplib
import re
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.utils import COMMASPACE, formatdate
def py_sendmail(send_from, send_to, subject,
text_body = None, html_body = None,
inline = False, authenticate = False, ssl = False,
smtp_server = None, port = 587, username = None,
password = None, send = True, attach_files = None,
debug = False):
img_content = []
msg = MIMEMultipart('related')
msg['From'] = send_from
msg['To'] = send_to
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
if inline == True:
img_re = re.compile("<img(?:.+?)src\s*=\s*(?P<quote>['\"])(?P<imgurl>.*?)(?P=quote)")
imgs = img_re.findall(html_body)
img_cnt = 1
for(q, imgurl) in imgs:
fp = open(imgurl, 'rb')
msg_img = MIMEImage(fp.read())
fp.close()
img_id = "image" + str(img_cnt)
msg_img.add_header("Content-ID", "<"+img_id+">")
img_content.append(msg_img)
html_body = re.sub(imgurl, "cid:"+img_id, html_body)
img_cnt = img_cnt + 1
if text_body is not None and html_body is not None:
msgAlt = MIMEMultipart('alternative')
msg.attach(msgAlt)
msgAlt.attach(MIMEText(text_body, 'plain'))
msgAlt.attach(MIMEText(html_body, 'html'))
elif text_body is not None:
msg.attach(MIMEText(text_body, 'plain'))
elif html_body is not None:
msg.attach(MIMEText(html_body, 'html'))
if attach_files is not None:
for f in attach_files or []:
with open(f, 'rb') as fil:
part = MIMEApplication(
fil.read(),
Name=basename(f)
)
part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
msg.attach(part)
if len(img_content) > 0:
for img in img_content:
msg.attach(img)
if send == True:
if ssl == True:
server = smtplib.SMTP_SSL(smtp_server, port)
else:
server = smtplib.SMTP(smtp_server, port)
if authenticate == True:
server.login(username, password)
x = server.sendmail(send_from, send_to, msg.as_string())
server.quit()
return x == {}
else:
return msg.as_string()
It should send an email and it does when sourced into the global environment or when loaded with devtools::load_all(). But if I install it with devtools::install_local() and library it, it crashes R. When I run it in RStudio it crashes without explanation, when I run it from the command line i get this:
> library(pymailr)
> pymailr:::py_sendmail("<from_address>", "<to_address>", "Test",
+ text_body = "Testing", html_body = "<h1>Testing</h1>",
+ inline = FALSE, authenticate = TRUE, ssl = TRUE,
+ smtp_server = "<smtp_server>", port = 465, username = "<user_name>",
+ password = "<password>", send = TRUE)
*** caught segfault ***
address (nil), cause 'memory not mapped'
Traceback:
1: py_call_impl(callable, dots$args, dots$keywords)
2: pymailr:::py_sendmail("<from_address>", "<to_address>", "Test", text_body = "Testing", html_body = "<h1>Testing</h1>", inline = FALSE, authenticate = TRUE, ssl = TRUE, smtp_server = "<smtp_server>", port = 465, username = "<username>", password = "<password>", send = TRUE)
Related
I have been trying to download all the YouTube comments on popular videos using python requests, but it has been throwing up the following error after about a quarter of the total comments:
{'error': {'code': 400, 'message': "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the request's input is invalid. Check the structure of the commentThread resource in the request body to ensure that it is valid.", 'errors': [{'message': "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the request's input is invalid. Check the structure of the commentThread resource in the request body to ensure that it is valid.", 'domain': 'youtube.commentThread', 'reason': 'processingFailure', 'location': 'body', 'locationType': 'other'}]}}
I found this thread detailing the same issue, and it seems that it is not possible to download all the comments on popular videos.
This is my code:
import argparse
import urllib
import requests
import json
import time
start_time = time.time()
class YouTubeApi():
YOUTUBE_COMMENTS_URL = 'https://www.googleapis.com/youtube/v3/commentThreads'
comment_counter = 0
with open("API_keys.txt", "r") as f:
key_list = f.readlines()
key_list = [key.strip('/n') for key in key_list]
def format_comments(self, results, likes_required):
comments_list = []
try:
for item in results["items"]:
comment = item["snippet"]["topLevelComment"]
likes = comment["snippet"]["likeCount"]
if likes < likes_required:
continue
author = comment["snippet"]["authorDisplayName"]
text = comment["snippet"]["textDisplay"]
str = "Comment by {}:\n \"{}\"\n\n".format(author, text)
str = str.encode('ascii', 'replace').decode()
comments_list.append(str)
self.comment_counter += 1
print("Comments downloaded:", self.comment_counter, end="\r")
except(KeyError):
print(results)
return comments_list
def get_video_comments(self, video_id, likes_required):
with open("API_keys.txt", "r") as f:
key_list = f.readlines()
key_list = [key.strip('/n') for key in key_list]
if self.comment_counter <= 900000:
key = self.key_list[0]
elif self.comment_counter <= 1800000:
key = self.key_list[1]
elif self.comment_counter <= 2700000:
key = self.key_list[2]
elif self.comment_counter <= 3600000:
key = self.key_list[3]
elif self.comment_counter <= 4500000:
key = self.key_list[4]
params = {
'part': 'snippet,replies',
'maxResults': 100,
'videoId': video_id,
'textFormat': 'plainText',
'key': key
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
}
try:
#data = self.openURL(self.YOUTUBE_COMMENTS_URL, params)
comments_data = requests.get(self.YOUTUBE_COMMENTS_URL, params=params, headers=headers)
except ChunkedEncodingError:
tries = 5
print("Chunked Error. Retrying...")
for n in range(tries):
try:
x = 0
x += 1
print("Trying", x, "times")
response = session.post("https://www.youtube.com/comment_service_ajax", params=params, data=data, headers=headers)
comments_data = json.loads(response.text)
except ChunkedEncodingError as c:
print(c)
results = comments_data.json()
nextPageToken = results.get("nextPageToken")
commments_list = []
commments_list += self.format_comments(results, likes_required)
while nextPageToken:
params.update({'pageToken': nextPageToken})
try:
comments_data = requests.get(self.YOUTUBE_COMMENTS_URL, params=params, headers=headers)
except ChunkedEncodingError as c:
tries = 5
print("Chunked Error. Retrying...")
for n in range(tries):
try:
x = 0
x += 1
print("Trying", x, "times")
response = session.post("https://www.youtube.com/comment_service_ajax", params=params, data=data, headers=headers)
comments_data = json.loads(response.text)
except ChunkedEncodingError as c:
print(c)
results = comments_data.json()
nextPageToken = results.get("nextPageToken")
commments_list += self.format_comments(results, likes_required)
return commments_list
def get_video_id_list(self, filename):
try:
with open(filename, 'r') as file:
URL_list = file.readlines()
except FileNotFoundError:
exit("File \"" + filename + "\" not found")
list = []
for url in URL_list:
if url == "\n": # ignore empty lines
continue
if url[-1] == '\n': # delete '\n' at the end of line
url = url[:-1]
if url.find('='): # get id
id = url[url.find('=') + 1:]
list.append(id)
else:
print("Wrong URL")
return list
def main():
yt = YouTubeApi()
parser = argparse.ArgumentParser(add_help=False, description=("Download youtube comments from many videos into txt file"))
required = parser.add_argument_group("required arguments")
optional = parser.add_argument_group("optional arguments")
here: https://console.developers.google.com/apis/credentials")
optional.add_argument("--likes", '-l', help="The amount of likes a comment needs to be saved", type=int)
optional.add_argument("--input", '-i', help="URL list file name")
optional.add_argument("--output", '-o', help="Output file name")
optional.add_argument("--help", '-h', help="Help", action='help')
args = parser.parse_args()
# --------------------------------------------------------------------- #
likes = 0
if args.likes:
likes = args.likes
input_file = "URL_list.txt"
if args.input:
input_file = args.input
output_file = "Comments.txt"
if args.output:
output_file = args.output
list = yt.get_video_id_list(input_file)
if not list:
exit("No URLs in input file")
try:
vid_counter = 0
with open(output_file, "a") as f:
for video_id in list:
vid_counter += 1
print("Downloading comments for video ", vid_counter, ", id: ", video_id, sep='')
comments = yt.get_video_comments(video_id, likes)
if comments:
for comment in comments:
f.write(comment)
print('\nDone!')
except KeyboardInterrupt:
exit("User Aborted the Operation")
# --------------------------------------------------------------------- #
if __name__ == '__main__':
main()
The next best method would be to randomly sample them. Does anyone know if this is possible with the API V3?
Even if the API returns a processingFailure error, you could still catch that (or any other API error for that matter) for to terminate gracefully your pagination loop. This way your script will provide the top-level comments that it fetched from of the API prior to the occurrence of the first API error.
The error response provided by the YouTube Data API is (usually) of the following form:
{
"error": {
"errors": [
{
"domain": <string>,
"reason": <string>,
"message": <string>,
"locationType": <string>,
"location": <string>
}
],
"code": <integer>,
"message": <string>
}
}
Hence, you could have defined the following function:
def is_error_response(response):
error = response.get('error')
if error is None:
return False
print("API Error: "
f"code={error['code']} "
f"domain={error['errors'][0]['domain']} "
f"reason={error['errors'][0]['reason']} "
f"message={error['errors'][0]['message']!r}")
return True
that you'll invoke after each statement of form results = comments_data.json(). In case of the first occurrence of that statement, you'll have:
results = comments_data.json()
if is_error_response(results):
return []
nextPageToken = results.get("nextPageToken")
For the second instance of that statement:
results = comments_data.json()
if is_error_response(results):
return comments_list
nextPageToken = results.get("nextPageToken")
Notice that the function is_error_response above prints out an error message on stdout in case its argument in an API error response; this is for the purpose of having the user of your script informed about the API call failure.
I have a strange issue with my python monitoring script:-
I've written a script with a number of alerts for any server. In that I have a function that gathers Network bytes/sec in and out.
Now the issue is when I print the alert outside my mail function it prints the current output, but for some reason when it triggers the mail for the alert, the mail body is empty. If I trigger the mail with another alert which isn't in the Network function it works properly.
Also is there a way to get smtplib to use port 587 instead of 465, any pointers on formatting the alert would be appreciated too.
Please find my script below:-
#!/usr/bin/env python3
#Module psutil needs to be installed via pip3 first.
#Python script to Monitor Server Resources.
import time
import psutil
import smtplib
from email.message import EmailMessage
project_and_instance_name = 'test-stage' #Edit the name of the project name and environment
sender = '<sender email>' #Email Address of the sender
receivers = ['recepient email'] #comma seperated list of recipients enclosed in ''
cpu_thresh = 50.0
cpu_pct = psutil.cpu_percent(interval=1)
if cpu_pct >= cpu_thresh:
cpu_alert = "CPU Warning, CPU at ",cpu_pct, "percent"
else:
cpu_alert = ""
mem = psutil.virtual_memory()
mem_thresh = 1024 * 1024 * 1024 #change the end value to choose the amount of MB
if mem_thresh >= mem.available:
mem_alert = "Memory Usage Warning only", round((mem.available /1024 /1024), 2), "MB available"
else:
mem_alert = ""
partition1 = '/'
disk1 = psutil.disk_usage(partition1)
disk_thresh = 85.0
if disk_thresh <= disk1[3]:
disk_alert = f"Root volume usage warning {disk1[3]} % used"
else:
disk_alert = ""
def net_usage(inf = "eth0"): #change the inf variable according to the interface
global net_in_alert
global net_out_alert
net_in_ps1 = psutil.net_io_counters(pernic=True, nowrap=True)[inf]
net_in_1 = net_in_ps1.bytes_recv
net_out_1 = net_in_ps1.bytes_sent
time.sleep(1)
net_in_ps2 = psutil.net_io_counters(pernic=True, nowrap=True)[inf]
net_in_2 = net_in_ps2.bytes_recv
net_out_2 = net_in_ps2.bytes_sent
net_in_res = round((net_in_2 - net_in_1) /1024 /1024, 2)
net_out_res = round((net_out_2 - net_out_1) /1024 /1024, 2)
net_in_thresh = 1.5
net_out_thresh = 1.5
if net_in_res >= net_in_thresh:
net_in_alert = f"Current net-usage:IN: {net_in_res} MB/s"
else:
net_in_alert = ""
if net_out_res <= net_out_thresh:
net_out_alert = f"Current net-usage:OUT: {net_out_res} MB/s"
else:
net_out_alert = ""
net_usage()
message_list = []
if cpu_alert == "" :
pass
else:
message_list.append(cpu_alert)
if mem_alert == "" :
pass
else:
message_list.append(mem_alert)
if disk_alert == "" :
pass
else:
message_list.append(disk_alert)
if net_in_alert == "" :
pass
else:
message_list.append(net_in_alert)
if net_out_alert == "" :
pass
else:
message_list.append(net_out_alert)
msg = '\n'.join(message_list)
print(msg)
def alerts():
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(sender, "<password>")
server.sendmail(sender,receivers,msg)
if msg == "":
pass
else:
alerts()
Got the answer by changing the SMTP format for any who are stuck here's the code:-
#!/usr/bin/env python3
#Module psutil needs to be installed via pip3 first.
#Python script to Monitor Server Resources.
import time
import psutil
import smtplib, ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
project_and_instance_name = 'test-stage' #Edit the name of the project name and environment
sender = '<senders email>' #Email Address of the sender
receivers = ['recepient email'] #comma seperated list of recipients enclosed in ''
cpu_thresh = 50.0
cpu_pct = psutil.cpu_percent(interval=1)
if cpu_pct >= cpu_thresh:
cpu_alert = "CPU Warning, CPU at ",cpu_pct, "percent"
else:
cpu_alert = ""
mem = psutil.virtual_memory()
mem_thresh = 1024 * 1024 * 1024 #change the end value to choose the amount of MB
if mem_thresh >= mem.available:
mem_alert = "Memory Usage Warning only", round((mem.available /1024 /1024), 2), "MB available"
else:
mem_alert = ""
partition1 = '/'
disk1 = psutil.disk_usage(partition1)
disk_thresh = 85.0
if disk_thresh <= disk1[3]:
disk_alert = f"Root volume usage warning {disk1[3]} % used"
else:
disk_alert = ""
def net_usage(inf = "eth0"): #change the inf variable according to the interface
global net_in_alert
global net_out_alert
net_in_ps1 = psutil.net_io_counters(pernic=True, nowrap=True)[inf]
net_in_1 = net_in_ps1.bytes_recv
net_out_1 = net_in_ps1.bytes_sent
time.sleep(1)
net_in_ps2 = psutil.net_io_counters(pernic=True, nowrap=True)[inf]
net_in_2 = net_in_ps2.bytes_recv
net_out_2 = net_in_ps2.bytes_sent
net_in_res = round((net_in_2 - net_in_1) /1024 /1024, 2)
net_out_res = round((net_out_2 - net_out_1) /1024 /1024, 2)
net_in_thresh = 1.5
net_out_thresh = 1.5
if net_in_res >= net_in_thresh:
net_in_alert = f"Current net-usage:IN: {net_in_res} MB/s"
else:
net_in_alert = ""
if net_out_res >= net_out_thresh:
net_out_alert = f"Current net-usage:OUT: {net_out_res} MB/s"
else:
net_out_alert = ""
net_usage()
message_list = []
if cpu_alert == "" :
pass
else:
message_list.append(cpu_alert)
if mem_alert == "" :
pass
else:
message_list.append(mem_alert)
if disk_alert == "" :
pass
else:
message_list.append(disk_alert)
if net_in_alert == "" :
pass
else:
message_list.append(net_in_alert)
if net_out_alert == "" :
pass
else:
message_list.append(net_out_alert)
msg = '\n'.join(message_list)
print(msg)
def alerts():
msg_template = MIMEMultipart()
msg_template['From'] = sender
msg_template['To'] = ', '.join(receivers)
msg_template['Subject'] = f"{project_and_instance_name} Alert"
msg_template.attach(MIMEText(msg, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(sender, "<password>")
server.sendmail(sender,receivers,msg_template.as_string())
server.quit()
if msg == "":
pass
else:
alerts()
Something helpful for me in understanding this answer -
receivers is a list of emails
receivers = ['email1', 'email2']
message template ["To"] is a joined string
msg_template['To'] = ', '.join(receivers)
server.sendmail() is the list of emails
server.sendmail(sender,receivers,msg_template.as_string())
With the script below i am trying to get the error text from a span error text box for first name when a name is not entered and the user clicks on the submit button, from a registration screen with the HTML below.(https://www.walmart.com/account/signup. However I end up just getting none instead of the text. When i try to get the text from chrome console i receive the text with the xpath and css selector as "$x("//span[#class='span-error']")[2]" and "$$(".span-error")[2]". I would like some guidance as to what I am missing, i think have tried everything i can think of.
Test case:
Get to the link Enter nothing on the first name,Get a validation
error Assert the validation error Enter an invalid name as ":::" Get
a validation error (they seem to have a couple)and so on
from time import sleep
from conftest import os
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
# LoginScreenSelectors
sel_first_name = "#first-name-su"
sel_last_name = "#last-name-su"
sel_email = "#email-su"
sel_password = "#password-su"
sel_error_message = ".span-error:nth-of-type(2)"
sel_submit = f"""[data-automation-id="signup-submit-btn"]"""
sel_required_error = f"""[data-error="required"]"""
class Login():
'''This will signup to the applcaiton '''
def __init__(self, driver):
self.driver = driver
wait = WebDriverWait(self.driver, 20)
self.first_name = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, sel_first_name))
)
self.last_name = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_last_name))
)
self.email = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_email))
)
self.password = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_password))
)
self.submit = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_submit))
)
def login_to_website(self):
wait = WebDriverWait(self.driver, 10)
print(self.driver.title)
self.first_name.click()
self.first_name.send_keys(" ")
self.first_name.send_keys(Keys.TAB)
self.first_name_error_message = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, sel_error_message))
)
type(self.first_name_error_message)
error_messages = []
for messages in self.first_name_error_message:
print(error_messages.append(messages.text))
#if i could get this then i could simply get the first index and then keep filtering
it but even that is proving to be difficult.
Try out this to get all elements with error messages
error_messages = self.driver.find_elements(By.XPATH, "//*[#id="sign-up-form"]/div/span[2]']")
This is how I ended up solving it.
Get the xpath as f"""[data-error="required"]""" and then with a for loop cycle through all the error messages for input fields, I hope this will help anyone that is trying to take a stab at validating happy and negative testing on the same testcase.
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
# LoginScreenSelectors
sel_first_name = "#first-name-su"
sel_last_name = "#last-name-su"
sel_email = "#email-su"
sel_password = "#password-su"
sel_submit = f"""[data-automation-id="signup-submit-btn"]"""
sel_required_error = f"""[data-error="required"]"""
class Register():
'''This wil register the user to the application '''
def __init__(self, driver):
self.driver = driver
wait = WebDriverWait(self.driver, 20)
self.first_name = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, sel_first_name))
)
self.last_name = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_last_name))
)
self.email = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_email))
)
self.password = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_password))
)
self.submit = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, sel_submit))
)
def login_to_website(self):
wait = WebDriverWait(self.driver, 10)
'''This will check for validaitons'''
self.last_name.send_keys("Test Automation Last Name")
self.email.send_keys("a#b.com")
self.password.send_keys("password")
self.submit.click()
self.first_name_error_message = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, sel_required_error))
)
for first_name_required_message in self.first_name_error_message:
first_name_message = first_name_required_message.text.replace("\n", ":")
# print(first_name_message)
# print(first_name_message[first_name_message.find(":") + 1:])
assert first_name_message[first_name_message.find(":") + 1:] == "First name is required."
sleep(1)
self.last_name.clear()
self.first_name.click()
self.first_name.send_keys("Test Automation First Name ")
self.submit.click()
self.last_name_error_message = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, sel_required_error)))
for last_name_required_message in self.last_name_error_message:
last_name_message = last_name_required_message.text.replace("\n", ":")
assert last_name_message[last_name_message.find(":") + 1:] == "Last name is required."
self.email.clear()
self.last_name.click()
self.last_name.send_keys("Test Automation Last Name ")
self.submit.click()
self.email_error_message = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, sel_required_error)))
for email_required_message in self.email_error_message:
email_message = email_required_message.text.replace("\n", ":")
assert email_message[email_message.find(":") + 1:] == "Email address is required."
self.password.clear()
self.email.click()
self.email.send_keys("your#email.com")
self.submit.click()
self.password_error_message = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, sel_required_error)))
'''only way i could assert it '''
for password_required_message in self.password_error_message:
password_message = password_required_message.text.replace("\n", " ")
assert password_message[password_message.find("d") + 1:]\
.replace(" ", "") == "passwordisrequired."
self.password.click()
self.password.send_keys("something123$")
self.submit.click()
Hello Everyone i need help why my output result is none in the print('bla bla') line so from my output is None, None, None that actually insert from npm , nama , and jurusan but the output is none ,can anybody help me solve it thanks
import sqlite3
import tkinter
from tkinter import *
from tkinter import ttk
def Daftar():
window = Tk()
window.title("Welcome to TutorialsPoint")
window.geometry('400x400')
window.configure(background = "grey");
Lnpm = Label(window, text="Please Input Your npm: ").grid(row=0, column=0)
Lnama = Label(window,text="Please Input Your nama: ").grid(row=1, column=0)
Ljurusan = Label(window,text="Please Input Your jurusan: ").grid(row=2, column=0)
npm = Entry(window).grid(row = 0,column = 1)
nama = Entry(window).grid(row = 1,column = 1)
jurusan = Entry(window).grid(row = 2,column = 1)
def Clicked():
print("First Name: %s\nLast Name: %s\nLast Name: %s" % (npm, nama, jurusan))
connect = sqlite3.connect('Presensi.db')
cur = connect.cursor()
connect.execute("INSERT OR IGNORE INTO user(npm,nama,jurusan) values(?,?,?)", (str(npm),str(nama),str(jurusan)))
connect.execute("INSERT OR IGNORE INTO presensi(nama) values(?)", (str(nama),))
connect.commit()
cur.close()
btn = ttk.Button(window ,text="Register",command= Clicked()).grid(row=3,column=0)
window.mainloop()
You've got two big issues here:
the grid() function of the Entry object returns None and that's what npm, nama and jurusan are None. What you have to do is store the Entry object, not the value returned from grid().
you're not calling get() on the Entry objects to get their input values
What you can do is create a class in which you store the Entry objects. The callback function of the Button object can then be a method of the class.
I've reorganised your code to do this:
from tkinter import Tk, Label, Button, Entry
import sqlite3
class Daftar:
def __init__(self, master):
self.window = master
self.window.title("Welcome to TutorialsPoint")
self.window.geometry('400x400')
self.window.configure(background = "grey");
self.Lnpm = Label(self.window, text="Please Input Your npm: ").grid(row=0, column=0)
self.Lnama = Label(self.window,text="Please Input Your nama: ").grid(row=1, column=0)
self.Ljurusan = Label(self.window,text="Please Input Your jurusan: ").grid(row=2, column=0)
#Entry objects for later use
self.npm = Entry(self.window)
self.npm.grid(row = 0,column = 1)
self.nama = Entry(self.window)
self.nama.grid(row = 1,column = 1)
self.jurusan = Entry(self.window)
self.jurusan.grid(row = 2,column = 1)
self.btn = Button(self.window ,text="Register",command = self.Clicked).grid(row=3,column=0)
def Clicked(self):
#Get the entry values
npm = self.npm.get()
nama = self.nama.get()
jurusan = self.jurusan.get()
print("First Name: %s\nLast Name: %s\nLast Name: %s" % (npm, nama, jurusan))
connect = sqlite3.connect('Presensi.db')
cur = connect.cursor()
connect.execute("INSERT OR IGNORE INTO user(npm,nama,jurusan) values(?,?,?)", (npm,nama,jurusan))
connect.execute("INSERT OR IGNORE INTO presensi(nama) values(?)", (nama,))
connect.commit()
cur.close()
root = Tk()
my_gui = Daftar(root)
root.mainloop()
window.mainloop()
I'm trying to request some data via the mt gox API (mtgox.com) and theres some example code in python that I'd like to basically copy into R.
import hmac, base64, hashlib, urllib2
base = 'https://data.mtgox.com/api/2/'
def makereq(key, secret, path, data):
hash_data = path + chr(0) + data
secret = base64.b64decode(secret)
sha512 = hashlib.sha512
hmac = str(hmac.new(secret, hash_data, sha512))
header = {
'User-Agent': 'My-First-Trade-Bot',
'Rest-Key': key,
'Rest-Sign': base64.b64encode(hmac),
'Accept-encoding': 'GZIP',
}
return urllib2.Request(base + path, data, header)
I have some R code already
install.packages("base64")
install.packages("caTools")
install.packages("digest")
install.packages("RCurl")
library(RCurl)
library(caTools)
library(base64)
base<- "https://data.mtgox.com/api/2"
path<- "BTCUSD/money/ticker"
APIkey<-"******" #this is private but its a long hex number
secretAPIkey<-"*****" #this too, but this is in base64
makeReq<-function(key, secret, path, post_data)
{
browser()
message <- paste(path, NULL, post_data)
secret<-base64decode(secret,"character")
theHmac <-hmac(secret,message,"sha512")
header <-
{
c(
User.Agent = "My Bot",
Rest.Key = key,
Rest.Sign = base64encode(theHmac),
Acccept.encoding = "GZIP"
)
}
return (getURL(paste(base,path), post_data, header) )
}
I don't know how to get the "header" thing to work though, and I might be using getURL() incorrectly.
If you want to see the whole problem, the instructions are here https://bitbucket.org/nitrous/mtgox-api/overview, scroll down to the first block of code.
but I'm probably just making some elementary mistake with R header syntax...
try to use postForm (from RCurl) instead of getURL:
postForm(paste(base,path),
.opts = list(postfields = post_data,
useragent = 'R',
httpheader = c('Rest-Key' = key,
'Rest-Sign' = base64encode(theHmac)),
timeout = 4,
ssl.verifypeer = FALSE)
)