I have created an add-on that outputs a csv file with the ratings of anki cards and the time they were rated.
In the anki-review_results folder, I stored an empty init.py, anki_rating_time_record.py, and a file named manifest.json, and after compressing it, I converted the extension to .ankiaddon.
However, I got the following error
An error occurred during the installation of anki-review-results.ankiaddon: Invalid add-on manifest.
Please report this to the add-on author in question.
Anki_rating_time_record.py is as follows
import anki_python_api
import csv
import datetime
# reset anki api
Anki = anki_python_api.
review_results = []
def review_did_answer_card(result, card, ease):
now = datetime.datetime.now()
review_results.append((result, card, ease, now))
# register Anki API
anki.add_review_did_answer_card_callback(review_did_answer_card)
# start anki
anki.run()
# save the results on csv format
with open("review_results.csv", "w") as f:
writer = csv.writer(f)
writer.writer(["timestamp", "result", "card", "ease"])
for all_results in review_results:
writer.writer([all_result[0].strftime("%Y-%m-%d %H:%M:%S"),all_result[1],
all_result[2],all_result[3]])
The manifest.json is as follows.
{
"id" : "anki-review-results",
"version": "0.1",
"name": "Anki Review Results",
"description": "Save the results of your Anki reviews in a CSV file",
"author": "Shohei",
"addonType":["background"],
"minimumAnkiVersion": "2.1.0"
"files":["Anki_rating_time_record.py","_init_.py"]
}
The version of anki in use is 2.1.58.
What can I do to make it function properly? Please let me know.
Related
I have developed a very basic Twitter bot using Python & Tweepy. It is successfully posting a tweet to twitter and I can modify the text in this line of code: response = client.create_tweet( text='Testing' ) to make different tweets
The full code I am using for this is:
import tweepy
client = tweepy.Client(consumer_key="XXXXX",
consumer_secret="XXXXX",
access_token="XXXXX",
access_token_secret="XXXXX")
# Create Tweet
response = client.create_tweet(
text='Testing'
)
print(f"https://twitter.com/user/status/{response.data['id']}")
What I am trying to figure out is how I can code a Bot to randomly read data stored in file(s) and put it altogether to formulate a readable sentence or paragraph a little bit like how a mailmerge works. Here is an example, there are 3 files or 3 values:
Value1
Check out this, View this, See this
Value 2
product, item, piece
Value 3
on our online shop, on our store, on our website
If the bot was able to read and select data at random it could pick any of the data from the files or values in any order, put them together and it would make sense as a sentence or a paragraph
After researching I see that using text or JSON files might be a possibility. I followed a JSON tutorial and recreated an example that looks like this for text and images:
[
{
"text": "hi",
"image": "/image1.jpg"
},
{
"text": "hello",
"image": "/image2.jpg"
}
]
I think I have worked out how to read the JSON file with this code:
import json
with open(r"C:\Users\Administrator\Desktop\Python\test.json") as f:
info = json.load(f)
randomChoice = random.randrange(len(info))
print (info[randomChoice])
The thing I am really struggling with is the best way to achieve this and how then to create the code that will post the tweet formulated with the random data it has selected
This is what I have so far as I attempt to combine Tweepy and the abilty to read in data from the JSON file but I can't get it to work as I don't know how to post the data it has read in to Twitter:
import tweepy
import random
import json
with open(r"C:\Users\Administrator\Desktop\Python\test.json") as f:
info = json.load(f)
client = tweepy.Client(consumer_key="XXXXX",
consumer_secret="XXXXX",
access_token="XXXXX",
access_token_secret="XXXXX")
# Create Tweet
randomChoice = random.randrange(len(info))
print (info[randomChoice])
response = client.create_tweet(
text='NOT SURE HOW TO CODE THIS PART SO TWEEPY POSTS RANDOMLY SELECTED DATA'
print(f"https://twitter.com/user/status/{response.data['id']}")
I am brand new to Python and Tweepy so have only a very small understanding but would really appreciate any help on it
About the storage:
You could read your file(s) and parse each line with the split(",") method, but JSON is probably a best solution since it is already formatted.
You want a list of alternatives (which are lists of strings), so why don't you simply use a list of lists ?
You JSON file would be like:
[
["Check out this", "View this", "See this"],
["product", "item", "piece"],
["on our online shop", "on our store", "on our website"]
]
About your Python code:
You don't need to generate a random index to select an element in a list:
randomChoice = random.randrange(len(info))
print (info[randomChoice])
The random module can do it for you:
random.choice(info)
About the sentence building:
You can now cross the main list, select an alternative from each list of alternatives and add it to the sentence that you will post:
full_sentence = ""
for alternatives in data:
selected_alternative = random.choice(alternatives)
full_sentence += ' ' + selected_alternative
The final code:
import json
import random
# You can start by loading the JSON file
with open(r"test.json") as f:
data = json.load(f)
# You can then build your full sentence
full_sentence = ""
for alternatives in data:
selected_alternative = random.choice(alternatives)
full_sentence += ' ' + selected_alternative
# You can now post your full sentence on Twitter
client = tweepy.Client(consumer_key="XXXXX", ...)
response = client.create_tweet(text=full_sentence)
Thanks very much for helping me to get this all working. I have been modifying the JSON file and tweaking the code and now have a script that is posting to twitter just as intended
Here is my final code:
import tweepy
import random
import json
# Start by loading the JSON file
with open(r"C:\Users\Administrator\Desktop\Twitterbot\test.json") as f:
data = json.load(f)
# Building the full sentence from values in JSON file
full_sentence = ""
for alternatives in data:
selected_alternative = random.choice(alternatives)
full_sentence += ' ' + selected_alternative
# You can now post your full sentence on Twitter
client = tweepy.Client(consumer_key="XXXXX",
consumer_secret="XXXXX",
access_token="XXXXX",
access_token_secret="XXXXX")
response = client.create_tweet(text=full_sentence)
print(f"https://twitter.com/user/status/{response.data['id']}")
Cheers
Jamie
I'm using python 3.6 and PyPDF2 to create bookmarks in a pdf.
Instead of adding a bookmark to a page within the pdf. I want to add a url (eg. https://stackoverflow.com) as a bookmark.
Something like this?
output.addBookmark('TEST', 'https://stackoverflow.com', parent=None)
I don't think PyPDF2 supports something like this or does it? Is there another library that can support this?
from PyPDF2 import PdfFileReader, PdfFileWriter
output = PdfFileWriter()
input = PdfFileReader(open('test.pdf', 'rb'))
output.addPage(input.getPage(0))
output.addBookmark('TEST', 0, parent=None) # add bookmark
outputStream = open('output.pdf', 'wb')
output.write(outputStream)
outputStream.close()
I might be a bit late but hear me out. I had to solve the same problem and since there is literally 0 information on this anywhere, I've investigated the issue and have managed to find the answer. It's not my most efficient/nicest code but definitely one of my proudest since nobody before did this.
The problem one faces is that there is no Pdf library for python that solves all
pdf related problems. Each tackle problems differently and some can do stuff that others can't. For this purpose, I had to use 2 libraries for the two functions below. PyPDF2 is here to add the bookmarks to the pdf. Pdfrw is here to alter those bookmarks to have the action of opening a url.
In short, we create a new pdf with the added bookmarks, and another new one with the changed bookmarks actions that point to a url.
One thing to mention is that for some reason (for me at least) PyPDF2 adds all bookmarks in a way that if you have multiple ones, they all become child elements to the previous bookmark. this is why we have the while loop, we collect all the bookmarks into a list with it, and then we can select the one we want.
If you already have bookmars and don't add them with PyPDF2, it might be enough to just loop over the metaObjects dictionary and get the values which contain the /Title key. Thus making the code significantly smaller. I've added this part as a comment.
Here an example on how to use the code below:
inputPdf = r"C:\......\first.pdf"
bookmarkedPdf = r"C:\......\second.pdf"
pdfWithWeblink = r"C:\......\final.pdf"
bookmarks = [
{"Title": "The Phantom Menace", "Page": 5},
{"Title": "Attack of the Clones", "Page": 10},
{"Title": "Revenge Of The Sith", "Page": 13},
{"Title": "A New hope", "Page": 18},
{"Title": "The Empire Strikes Back", "Page": 26},
{"Title": "Return of the Jedi", "Page": 32}
]
AddBookmarks(inputPdf, bookmarkedPdf, bookmarks)
AddWebLinkToBookmark(bookmarkedPdf, pdfWithWeblink, "Revenge Of The Sith", "https://stackoverflow.com")
The code:
from PyPDF2 import PdfFileWriter, PdfFileReader
import pdfrw
def AddBookmarks(inputPdfPath: str, outputPdfPath: str, headers: dict) -> None:
""" Adds bookmarks to a PDF. """
output = PdfFileWriter()
input = PdfFileReader(open(inputPdfPath, 'rb'))
for i in range(input.getNumPages()):
output.addPage(input.getPage(i))
for header in headers:
if header["Page"] - 1 == i:
output.addBookmark(header["Title"], header["Page"] - 1, parent=None)
output.setPageMode("/UseOutlines")
outputStream = open(outputPdfPath,'wb')
output.write(outputStream)
outputStream.close()
return outputPdfPath
def AddWebLinkToBookmark(inputPdfPath: str, outputPdfPath: str, bookmarkTitle: str, url: str) -> None:
""" Changes the bookmark action to opening a web url. """
# Reading the Pdf with pdfrw and collecting its meta objects. The bookmarks are among these.
pdf = pdfrw.PdfReader(inputPdfPath, decompress=True)
metaObjects = pdf.indirect_objects
# If you did not add the bookmarks with PyPDF2 previously, use this part for getting the bookmarkToChange variable:
# bookmarkToChange = None
# for _, annotation in metaObjects.items():
# if '/Title' in annotation:
# if annotation["/Title"] == f"({bookmarkTitle})".replace(" ", "\\040"):
# bookmarkToChange = annotation
# if bookmarkToChange == None:
# print(f"There is no bookmark called '{bookmarkTitle}' in this pdf.")
# return
try:
# Selecting the first, top parent bookmark.
bookmark = [annotation for _, annotation in metaObjects.items() if '/Title' in annotation][0]
except IndexError:
print("There are no bookmarks in this pdf.")
return
# Each bookmark is the child of the previous bookmark. They can be accessed from the parent with the '/Next' key.
bookmarkAnnotations = [bookmark]
while "/Next" in bookmark:
if "/Title" not in bookmark["/Next"]:
break
bookmark = bookmark["/Next"]
bookmarkAnnotations.append(bookmark)
try:
# Selecting the bookmark we want to add the url to.
bookmarkToChange = [annotation for annotation in bookmarkAnnotations if annotation["/Title"] == f"({bookmarkTitle})".replace(" ", "\\040")][0]
except IndexError:
print(f"There is no bookmark called '{bookmarkTitle}' in this pdf.")
return
# Changing the internal PDF commands to point to a url instead of a page.
bookmarkToChange.A.D = None # Deletes the page information the 'Go to page' action is pointing to.
bookmarkToChange.A.S = pdfrw.PdfName("URI") # Changes the 'Go to page' action to an 'Open a web link' action.
bookmarkToChange.A.URI = pdfrw.objects.pdfstring.PdfString(f"({url})") # Specifies the url for the 'Open a web link' action.
# Saving the end result into a new file.
pdfrw.PdfWriter().write(outputPdfPath, pdf)
I am trying to write a Python Script to parse through a PDF file using PyPDF2. Only thing is, my PDF file isnt your traditional document, it's an engineering drawing.
Anyway, I need the code to parse through the text that is written on the bottom right corner, as well as a red stamp that has text written on it. The drawing will look something like this: enter image description here
I tried to write some basic code to just parse it and extract the data, but its not working.
import PyPDF2
# creating a pdf file object
pdfFileObj = open('example.pdf', 'rb')
# creating a pdf reader object
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
# printing number of pages in pdf file
print(pdfReader.numPages)
# creating a page object
pageObj = pdfReader.getPage(0)
# extracting text from page
print(pageObj.extractText())
# closing the pdf file object
pdfFileObj.close()
Anyone have any recomendations?
Late to the party...
None the less, we developed a commercial product to do exactly that: Werk24. It has a simple python client pip install werk24
With this your task becomes very simple. You can read the Title Block with a simple command. Imagine you want to obtain the Designation
from werk24 import Hook, W24AskTitleBlock
from werk24.models.techread import W24TechreadMessage
from werk24.utils import w24_read_sync
from . import get_drawing_bytes # define your own
def recv_title_block(message: W24TechreadMessage) -> None:
""" Print the Designation
NOTE: Other fields like Drawing ID, Material etc are
also available.
"""
print(message.payload_dict.get('designation'))
if __name__ == "__main__":
# submit the request to Werk24
w24_read_sync(
get_drawing_bytes(),
[Hook(
ask=W24AskTitleBlock(),
function=recv_title_block
)])
For the drawing that your provided, the response will be:
"designation": {
"captions": [
{
"language": "eng",
"text": "Descr"
}
],
"values": [
{
"language": "eng",
"test": "Shaft",
}
]
}
NOTE: Your files is very blurry, so I created the response manually - the API requires a minimal resolution of 180 dpi (also works with TIF and DXF files).
I'm not understanding the documentation on using Mako templates in python. I have a python file and I have the following code:
import json, requests, urllib2
from mako.template import Template
from mako.lookup import TemplateLookup
from pylons.templating import render_mako as render
url="www.data&format=json"
response = urllib2.urlopen(url)
data = json.load(response)
return (Template("hello Luisito! Here is the data: ${data}!").render(json_data=data))
could someone provide me with some more detail on how to render this json data into a webpage using the mako template? do i need another file with the template? if so, how?
You need to add a variable for the json data:
url="www.data&format=json"
response = urllib2.urlopen(url)
data = json.load(response)
from mako.template import Template
print(Template("hello Luisito! Here is the data: ${json_data}!").render(json_data=data))
from mako.template import Template
from mako.lookup import TemplateLookup
from mako import exceptions
from mako.exceptions import RichTraceback
import json
var data = {
"Records": [
{
"pageName":"oracle.html",
"seoMetaData":"A page's description, usually one or two sentences.",
"logoImg":"./images/oracle-cloud-logo-400x336.png",
"logoImgUrl":"http://www.oracle.com",
"description": "Oracle Cloud is a cloud computing service offered by Oracle Corporation providing servers, storage, network, applications and services through a global network of Oracle Corporation managed data centers. The company allows these services to be provisioned on demand over the Internet. Also, we provide the list of companies that use Oracle Cloud.",
"product": "Oracle",
"category": "CRM & Related",
"customerAccount": "125,000 - 150,000"
},
{
"pageName":"microsoft.html",
"seoMetaData":"A page's description, usually one or two sentences.",
"logoImg":"./images/oracle-cloud-logo-400x336.png",
"logoImgUrl":"http://www.microsoft.com",
"description": "Microsoft Cloud is a cloud computing service offered by Microsoft Corporation providing servers, storage, network, applications and services through a global network of Microsoft Corporation managed data centers. The company allows these services to be provisioned on demand over the Internet. Also, we provide the list of companies that use Microsoft Cloud.",
"product": "Microsoft",
"category": "CRM & Related",
"customerAccount": "200,000 - 250,000"
}
]
}
mylookup = TemplateLookup(directories=['./html'], output_encoding='utf-8', encoding_errors='replace')
uri = 'base.html'
def browseLocal(webpageText, filename):
'''Start your webbrowser on a local file containing the text
with given filename.'''
import webbrowser, os.path
strToFile(webpageText, filename)
# webbrowser.open("file:///" + os.path.abspath(filename)) #elaborated for Mac.
def strToFile(text, filename):
"""Write a file with the given name and the given text."""
output = open(filename,"w")
output.write(text)
output.close()
def fileToStr(fileName): # NEW
"""Return a string containing the contents of the named file."""
fin = open(fileName);
contents = fin.read();
fin.close()
return contents
f = open("data.json", "r")
data = f.read()
jsonData = json.loads(data)
list1 = jsonData["Records"]
for val in list1:
pageName = val["pageName"]
seoMetaData = val["seoMetaData"]
logoImg = val["logoImg"]
logoImgUrl = val["logoImgUrl"]
description = val["description"]
product = val["product"]
category = val["category"]
customerAccount = val["customerAccount"]
template = mylookup.get_template(uri)
htmlContent = template.render_unicode(name=pageName, seoMetaData=seoMetaData, logoImg=logoImg, logoImgUrl=logoImgUrl, description=description, product=product, category=category, customerAccount=customerAccount)
browseLocal(htmlContent, pageName)
f.close()
I have the code below
from PyPDF2 import PdfFileReader, PdfFileWriter
d = {
"Name": "James",
" Date": "1/1/2016",
"City": "Wilmo",
"County": "United States"
}
reader = PdfFileReader("medicareRRF.pdf")
inFields = reader.getFields()
watermark = PdfFileReader("justSign.pdf")
writer = PdfFileWriter()
page = reader.getPage(0)
page.mergePage(watermark.getPage(0))
writer.addPage(page)
written_page = writer.getPage(0)
writer.updatePageFormFieldValues(written_page, d)
Which correctly fills in the PDF with the dictionary (d), but how can I check and uncheck boxes on the PDF? Here is the getField() info for one of the boxes:
u'Are you ok': {'/FT': '/Btn','/Kids': [IndirectObject(36, 0),
IndirectObject(38, 0)],'/T': u'Are you ok','/V': '/No'}
I tried adding {'Are you ok' : '/Yes'} and several other similar ways, but nothing worked.
I came across the same issue, looked in several places, and was disappointed that I couldn't find the answer. After a few frustrating hours looking at my code, the pyPDF2 code, and the Adobe PDF 1.7 spec, I finally figured it out. If you debug into updatePageFormFieldValues, you'll see that it uses only TextStringObjects. Checkboxes are not text fields -- even the /V values are not text fields, which seemed counterintuitive at least to me. Debugging into that function showed me that checkboxes are instead NameObjects so I created my own function to handle them. I create two dicts: one with only text values that I pass to the built-in updatePageFormFieldValues function and a second with only checkbox values. I also set the /AS to ensure visibility (see PDF spec). My function looks like this:
def updateCheckboxValues(page, fields):
for j in range(0, len(page['/Annots'])):
writer_annot = page['/Annots'][j].getObject()
for field in fields:
if writer_annot.get('/T') == field:
writer_annot.update({
NameObject("/V"): NameObject(fields[field]),
NameObject("/AS"): NameObject(fields[field])
})
However, as far as I can tell, whether you use /1, /On, or /Yes depends on how the form was defined or perhaps what the PDF reader is looking for. For me, /1 worked.
I will like to add on to the answer #rpsip.
from PyPDF2 import PdfReader, PdfWriter
from PyPDF2.generic import NameObject
reader = PdfReader(r"form2.pdf") #where you read the pdf in the same directory
writer = PdfWriter()
page = reader.pages[0] #read page 1 of your pdf
fields = reader.get_fields()
print (fields) # this is to identify if you can see the form fills in that page
writer.add_page(page) #this line is necessary otherwise the pdf will be corrupted
for i in range(len(page["/Annots"])): #in order to access the "Annots" key
print ((page["/Annots"][i].get_object())) #to find out which of the form fills are checkbox or text fill
if (page["/Annots"][i].get_object())['/FT']=="/Btn" and (page["/Annots"][i].get_object())['/T']=='Check Box3': #this is my filter so that I can filter checkboxes and the checkbox I want i.e. "Check Box 3"
print (page["/Annots"][i].get_object()) #further check if I got what I wanted as per the filter
writer_annot = page["/Annots"][i].get_object()
writer_annot.update(
{
NameObject("/V"): NameObject(
"/Yes"), #NameObject being only for checkbox, and please try "/Yes" or "/1" or "/On" to see which works
NameObject("/AS"): NameObject(
"/Yes" #NameObject being only for checkbox, and please try "/Yes" or "/1" or "/On" to see which works
)
}
)
with open("filled-out.pdf", "wb") as output_stream:
writer.write(output_stream) #save the ticked pdf file as another file named "filled-out.pdf"
hoped I helped.