Cannot write white spaces in a Alert object in ipyvuetify - python

I try to display n progress bar in an Alert (instead of using the vuetify progress element I know).
I created a little script that does a nice output as a str :
def update_progress(progress, msg='Progress', bar_length=30):
plain_char = '█'
empty_char = ' '
progress = float(progress)
block = int(round(bar_length * progress))
text = f'{msg}: |{plain_char * block + empty_char * (bar_length - block)}| {progress *100:.1f}%'
return text
when I print the output, I get the following :
and when I insert it as a child in an Alert component :
First problem, the spaces have been trimed, second problem it's changing the block ascii character to a wider one.
Is it normal and how can I avoid it?

As referenced in the github repository of the ipyvuetify lib (#103), it's a 'feature' of HTML: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace
Using the pre tag will preserve whitespace:
v.Html(
tag='pre',
children=['a mess age'],
class_='info--text',
style_='font-family:roboto'
)
The class and style traitlets are here to keep the formating of the Alert (need to be adapted to your own type_)

Related

underline text with odfpy

I'd like to generate an odf file with odfpy, and am stuck on underlining text.
Here is a minimal example inspired from official documentation, where i can't find any information about what attributes can be used and where.
Any suggestion?
from odf.opendocument import OpenDocumentText
from odf.style import Style, TextProperties
from odf.text import H, P, Span
textdoc = OpenDocumentText()
ustyle = Style(name="Underline", family="text")
#uprop = TextProperties(fontweight="bold") #uncommented, this works well
#uprop = TextProperties(attributes={"fontsize":"26pt"}) #this either
uprop = TextProperties(attributes={"underline":"solid"}) # bad guess, wont work !!
ustyle.addElement(uprop)
textdoc.automaticstyles.addElement(ustyle)
p = P(text="Hello world. ")
underlinedpart = Span(stylename=ustyle, text="This part would like to be underlined. ")
p.addElement(underlinedpart)
p.addText("This is after the style test.")
textdoc.text.addElement(p)
textdoc.save("myfirstdocument.odt")
Here is how I finally got it:
I created a sample document with underlining using libreoffice, and unzipped it. Looking in styles.xml part of the extracted files, I got the part that makes underlining in the document:
<style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text">
<style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/>
</style:style>
The interesting style attributes are named: text-underline-style,
text-underline-width and text-underline-color.
To use them in odfpy, '-' characters must be removed, and attributes keys must be used as str (with quotes) like in the following code. A correct style family (text in our case) must be specified in the Style constructor call.
from odf.opendocument import OpenDocumentText
from odf.style import Style, TextProperties
from odf.text import H, P, Span
textdoc = OpenDocumentText()
#underline style
ustyle = Style(name="Underline", family="text") #here style family
uprop = TextProperties(attributes={
"textunderlinestyle":"solid",
"textunderlinewidth":"auto",
"textunderlinecolor":"font-color"
})
ustyle.addElement(uprop)
textdoc.automaticstyles.addElement(ustyle)
p = P(text="Hello world. ")
underlinedpart = Span(stylename=ustyle, text="This part would like to be underlined. ")
p.addElement(underlinedpart)
p.addText("This is after the style test.")
textdoc.text.addElement(p)
textdoc.save("myfirstdocument.odt")

Progress bar in Sublime Text with Python

I am using the powerful Sublime Text 3 editor on MacOSX to run python codes. I want to display a progress bar of a for loop, and the following command:
sys.stdout.write('\rProgress : %03.2f %%' % (100*float(i)/(N)))
sys.flush()
does not clear the previously printed line in the output window as expected (\r) but produces N lines:
Progress : 0.25 %
Progress : 0.50 %
Progress : 0.75 %
Progress : 1.00 %
Progress : 1.25 %
Progress : 1.50 %
Progress : 1.75 %
Progress : 2.00 %
Progress : 2.25 %
Progress : 2.50 %
...
Which is not really nice to read – I conclude that the output window might be read-only.
Does anyone have suggestions to improve the use of progress bars in Sublime Text?
As another alternative solution you can use status bar. When you you set the status bar message the previous text is cleared. Package control also uses status bar while installing packages.
Example:
import sublime, sublime_plugin
import time
class ExampleCommand(sublime_plugin.WindowCommand):
def run(self, args):
sublime.set_timeout_async(self.test,1)
def test(self):
i=80
while i <= 100:
sublime.status_message('%03.2f %%' % i)
time.sleep(0.15)
i+=0.25
sublime.status_message('100% Stackoverflow!')
Taking a look at sublime.py we see that the flush method actually does nothing:
class _LogWriter:
def flush(self):
pass
def write(self, s):
sublime_api.log_message(s)
sys.stdout = _LogWriter()
sys.stderr = _LogWriter()
However I would not recommend to use the console for user outputs anyway. Usually you use output panels/views or status messages.
Status messages are easier to use, but less powerful. sergioFC demonstrated this in his answer.
This demonstrates how to use an output panel. It is very flexible, but you must write your own text command to insert the text. This is necessary, because you need an edit object to change the content of the view.
import sublime
import sublime_plugin
class MyInsertProgressBarCommand(sublime_plugin.TextCommand):
def run(self, edit, value):
view = self.view
width, _ = view.viewport_extent()
em_width = view.em_width()
# the number of columns are the width divided by the width of a char
# subtract two to add a little border
columns = int(width / em_width) - 2
# subtract two, because we surround it with [ and ]
bar_length = columns - 2
# calculate the size of the filled and the remaining part
filled_length = int(bar_length * value / 100)
remaining_length = bar_length - filled_length
# assemble the string for the progress bar
text = "[{0}{1}]\n".format("=" * filled_length, "." * remaining_length)
# add the text for the percentages
if value >= 100:
percentage_text = "finished!"
else:
percentage_text = "{:3.2f} %".format(value)
text += " " * (columns - len(percentage_text)) + percentage_text
# replace the content of the view
view.replace(edit, sublime.Region(0, view.size()), text)
# reset sels
view.sel().clear()
view.sel().add(sublime.Region(0, 0))
class ProgressBarCommand(sublime_plugin.WindowCommand):
def run(self):
self.window.create_output_panel("progess_bar")
self.window.run_command("show_panel", {"panel": "output.progess_bar"})
def test_progress_bar():
import random
test_progress_bar.value += 2 * random.random()
if test_progress_bar.value >= 100:
self.finish_progress()
return
self.show_progress(test_progress_bar.value)
sublime.set_timeout(test_progress_bar, 100)
test_progress_bar.value = 0
sublime.set_timeout_async(test_progress_bar, 1)
def show_progress(self, progess):
view = self.window.find_output_panel("progess_bar")
view.run_command("my_insert_progress_bar", {"value": progess})
def finish_progress(self):
self.show_progress(100)
sublime.set_timeout(self._destroy, 5000)
def _destroy(self):
self.window.destroy_output_panel("progess_bar")
The output:
You can create a visual progress bar using:
the mdpopups library
sublime.set_timeout or sublime.set_timeout_async ( see: Sublime Module )
 
Demo:
 
Code:
# GitHub
( run the plugin by typing Progress Bar Demo # the Command Palette )
 
 
Notes:
There is a css file that controls the style of mdpopups.
For some reason, the color property isn't having any effect.
Also, mdpopups.show_popup's location parameter takes -1 for the popup to be set at the caret position.
Otherwise, I'm not sure how location affects the popup, since it only takes a single integer value.  
 
I've inquired about these issues at the following thread:
[Proof Of Concept] Visual Progress Bar
 
Unfortunately, this is not possible in Sublime's output panel. The panel is not a true console or terminal, and among other differences does not interpret escape sequences such as \r and \b (\n is interpreted correctly, however). If you want to see how exactly it works, install PackageResourceViewer, then open Packages/Default/exec.py.
In order to get this to work, you'll need to create a new build system to run it in Terminal. Due to the vagaries of OS X, you'll need to create two files. The first is a shell script:
#!/bin/sh
osascript -e '
on run parameters
tell application "Terminal"
activate
do script with command "/path/to/python " & parameters
end tell
end run
' $#
Change /path/to with your actual path to python (or python3). Save it wherever you want as PythonTerminal.sh. Next, select Tools -> Build System -> New Build System and paste in the following:
{
"cmd": ["/bin/sh /path/to/Python3Terminal.sh \"$file\""],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"shell": true
}
Again, change /path/to to the actual path to PythonTerminal.sh. Save the file as Packages/User/PythonTerminal.sublime-build (it should automatically open the correct directory when saving).
Finally, select Tools -> Build System -> PythonTerminal, switch to your Python file, and build with ⌘B. A new Terminal window will open and your progress bar should run.
What you might be looking for is a way to keep the output from consuming multiple lines. You can print \b (the backspace character) as many times as there were previously printed characters. I wrote this as an example:
(Python 2.7.6)
from __future__ import print_function
import time, sys
for i in range(1, 6):
print(i, end='')
sys.stdout.flush()
time.sleep(0.5)
print('\b', end='')
Try running that and you can adapt it to your needs.
You can use progressbar library. located here : https://pypi.python.org/pypi/progressbar/2.3-dev
Also you can install it from easy_install just type : easy_install progressbar
Example to use :
if you want simple progressbar with out information about function :
from progressbar import *
from time import sleep
progress = ProgressBar()
for i in progress(range(80)):
sleep(0.01)
else if you want progressbar with information about function :
from progressbar import *
from time import sleep
widgets = ['Something: ', Percentage(), ' ', Bar(marker=RotatingMarker()),
' ', ETA(), ' ', FileTransferSpeed()]
pbar = ProgressBar(widgets=widgets, maxval=10000000).start()
for i in range(1000000):
# do something
pbar.update(10*i+1)
sleep(0.000001)
pbar.finish()

Remove tkinter text default binding

I'm making a simple tkinter Text editor, but i want all default bindings of the Text widget removed if possible.
For example when i press Ctrl + i it inserts a Tab character by default.
I made an event binding that prints how many lines are in the text box, I set the event binding to Ctrl + i as well.
When i run it, It prints the number of lines inside the text box, but also inserts a tab character.
I want to know how i can Overwrite the default bindings, or learna way how to remove all the default bindings.
Heres my code btw:
from tkinter import *
class comd: # Contains primary commands
# Capital Rule ----------------------------
# G = Get | I = Insert | D = Draw | S = Set
# -----------------------------------------
def Ggeo(self): # Get Geometry (Get window geometry)
x = root.winfo_width()
y = root.winfo_height()
print("Current Window Geometry")
print(str(x) + " x " +str(y))
def Idum(self): # Insters "Dummy Insert"
import tkinter as tkin
tbox.insert(INSERT, "Dummy Insert")
def Ilim(self): # Prints How many lines are in
info = int(tbox.index('end-1c').split('.')[0])
print(info)
root = Tk()
root.geometry("885x600-25-25")
tbox = Text(root, font=("Courier","14","bold"))
tbox.pack(expand = True , fill = BOTH)
# Problem here --------------------
tbox.bind("<Control-i>", comd.Ilim)
# ---------------------------------
mainloop()
You can overwrite a binding by having your function return the string "break". For example:
def Ilim(self): # Prints How many lines are in
info = int(tbox.index('end-1c').split('.')[0])
print(info)
return "break"
If you want to completely remove all bindings (including the bindings that allow you to insert characters), that can be easily accomplished. All of the bindings are associated with a "bind tag" (or "bindtag"). If you remove the bindtag, you remove the bindings.
For example, this removes all of the default bindings:
bindtags = list(tbox.bindtags())
bindtags.remove("Text")
tbox.bindtags(tuple(bindtags))
For more information on bind tags, see this answer: https://stackoverflow.com/a/11542200/7432

How to color specific part of the text with some separator

I'm trying to color some specific part of the text, i have tried to say:
if word.strip().startswith(":"):
self.setAttributesForRange(NSColor.greenColor(), None, highlightOffset, len(word))
When someone types the sign : it gets colored green. That is good, but it keeps coloring the word after it like this:
:Hello Hello :Hello <---- this all gets colored green, but I want something like:
:Hello Hello :Hello <---- where everything get colored except the middle "hello" because it doesn't start with the sign : , please help me out
from Foundation import *
from AppKit import *
import objc
class PyObjC_HighlightAppDelegate(NSObject):
# The connection to our NSTextView in the UI
highlightedText = objc.IBOutlet()
# Default font size to use when highlighting
fontSize = 12
def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
def textDidChange_(self, notification):
"""
Delegate method called by the NSTextView whenever the contents of the
text view have changed. This is called after the text has changed and
been committed to the view. See the Cocoa reference documents:
http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSText_Class/Reference/Reference.html
http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSTextView_Class/Reference/Reference.html
Specifically the sections on Delegate Methods for information on additional
delegate methods relating to text control is NSTextView objects.
"""
# Retrieve the current contents of the document and start highlighting
content = self.highlightedText.string()
self.highlightText(content)
def setAttributesForRange(self, color, font, rangeStart, rangeLength):
"""
Set the visual attributes for a range of characters in the NSTextView. If
values for the color and font are None, defaults will be used.
The rangeStart is an index into the contents of the NSTextView, and
rangeLength is used in combination with this index to create an NSRange
structure, which is passed to the NSTextView methods for setting
text attributes. If either of these values are None, defaults will
be provided.
The "font" parameter is used as an key for the "fontMap", which contains
the associated NSFont objects for each font style.
"""
fontMap = {
"normal" : NSFont.systemFontOfSize_(self.fontSize),
"bold" : NSFont.boldSystemFontOfSize_(self.fontSize)
}
# Setup sane defaults for the color, font and range if no values
# are provided
if color is None:
color = NSColor.blackColor()
if font is None:
font = "normal"
if font not in fontMap:
font = "normal"
displayFont = fontMap[font]
if rangeStart is None:
rangeStart = 0
if rangeLength is None:
rangeLength = len(self.highlightedText.string()) - rangeStart
# Set the attributes for the specified character range
range = NSRange(rangeStart, rangeLength)
self.highlightedText.setTextColor_range_(color, range)
self.highlightedText.setFont_range_(displayFont, range)
def highlightText(self, content):
"""
Apply our customized highlighting to the provided content. It is assumed that
this content was extracted from the NSTextView.
"""
# Calling the setAttributesForRange with no values creates
# a default that "resets" the formatting on all of the content
self.setAttributesForRange(None, None, None, None)
# We'll highlight the content by breaking it down into lines, and
# processing each line one by one. By storing how many characters
# have been processed we can maintain an "offset" into the overall
# content that we use to specify the range of text that is currently
# being highlighted.
contentLines = content.split("\n")
highlightOffset = 0
for line in contentLines:
if line.strip().startswith("#"):
# Comment - we want to highlight the whole comment line
self.setAttributesForRange(NSColor.greenColor(), None, highlightOffset, len(line))
elif line.find(":") > -1:
# Tag - we only want to highlight the tag, not the colon or the remainder of the line
startOfLine = line[0: line.find(":")]
yamlTag = startOfLine.strip("\t ")
yamlTagStart = line.find(yamlTag)
self.setAttributesForRange(NSColor.blueColor(), "bold", highlightOffset + yamlTagStart, len(yamlTag))
elif line.strip().startswith("-"):
# List item - we only want to highlight the dash
listIndex = line.find("-")
self.setAttributesForRange(NSColor.redColor(), None, highlightOffset + listIndex, 1)
# Add the processed line to our offset, as well as the newline that terminated the line
highlightOffset += len(line) + 1
It all depends on what word is.
In [6]: word = ':Hello Hello :Hello'
In [7]: word.strip().startswith(':')
Out[7]: True
In [8]: len(word)
Out[8]: 19
Compare:
In [1]: line = ':Hello Hello :Hello'.split()
In [2]: line
Out[2]: [':Hello', 'Hello', ':Hello']
In [3]: for word in line:
print word.strip().startswith(':')
print len(word)
...:
True
6
False
5
True
6
Notice the difference in len(word), which I suspect is causing your problem.

Showing page count with ReportLab

I'm trying to add a simple "page x of y" to a report made with ReportLab.. I found this old post about it, but maybe six years later something more straightforward has emerged? ^^;
I found this recipe too, but when I use it, the resulting PDF is missing the images..
I was able to implement the NumberedCanvas approach from ActiveState. It was very easy to do and did not change much of my existing code. All I had to do was add that NumberedCanvas class and add the canvasmaker attribute when building my doc. I also changed the measurements of where the "x of y" was displayed:
self.doc.build(pdf)
became
self.doc.build(pdf, canvasmaker=NumberedCanvas)
doc is a BaseDocTemplate and pdf is my list of flowable elements.
use doc.multiBuild
and in the page header method (defined by "onLaterPages="):
global TOTALPAGES
if doc.page > TOTALPAGES:
TOTALPAGES = doc.page
else:
canvas.drawString(270 * mm, 5 * mm, "Seite %d/%d" % (doc.page,TOTALPAGES))
Just digging up some code for you, we use this:
SimpleDocTemplate(...).build(self.story,
onFirstPage=self._on_page,
onLaterPages=self._on_page)
Now self._on_page is a method that gets called for each page like:
def _on_page(self, canvas, doc):
# ... do any additional page formatting here for each page
print doc.page
I came up with a solution for platypus, that is easier to understand (at least I think it is). You can manually do two builds. In the first build, you can store the total number of pages. In the second build, you already know it in advance. I think it is easier to use and understand, because it works with platypus level event handlers, instead of canvas level events.
import copy
import io
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import inch
styles = getSampleStyleSheet()
Title = "Hello world"
pageinfo = "platypus example"
total_pages = 0
def on_page(canvas, doc: SimpleDocTemplate):
global total_pages
total_pages = max(total_pages, doc.page)
canvas.saveState()
canvas.setFont('Times-Roman', 9)
canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, total_pages))
canvas.restoreState()
Story = [Spacer(1, 2 * inch)]
style = styles["Normal"]
for i in range(100):
bogustext = ("This is Paragraph number %s. " % i) * 20
p = Paragraph(bogustext, style)
Story.append(p)
Story.append(Spacer(1, 0.2 * inch))
# You MUST use a deep copy of the story!
# https://mail.python.org/pipermail/python-list/2022-March/905728.html
# First pass
with io.BytesIO() as out:
doc = SimpleDocTemplate(out)
doc.build(copy.deepcopy(Story), onFirstPage=on_page, onLaterPages=on_page)
# Second pass
with open("test.pdf", "wb+") as out:
doc = SimpleDocTemplate(out)
doc.build(copy.deepcopy(Story), onFirstPage=on_page, onLaterPages=on_page)
You just need to make sure that you always render a deep copy of your original story. Otherwise it won't work. (You will either get an empty page as the output, or a render error telling that a Flowable doesn't fit in the frame.)

Categories