File length limit when setting background in Finder window from Python script - python

I am interested in creating a dmg disk image on MacOS X from Python, and came across the following solution: How do I create a nice-looking DMG for Mac OS X using command-line tools?
However, I am running into a strange issue related to path lengths. The following script illustrates my problem:
import os
import Image
for NAME in ['works', 'doesnotwork']:
if os.path.exists(NAME + '.dmg'):
os.remove(NAME + '.dmg')
if os.path.exists('/Volumes/' + NAME):
raise Exception("Need to eject /Volumes/%s first" % NAME)
nx = 256
ny = 256
image = Image.new("RGB", (nx, ny))
for i in range(nx):
for j in range(ny):
image.putpixel((i, j), (i, 0, j))
os.system('hdiutil create -volname %s -fs HFS+ -size 10m %s.dmg' % (NAME, NAME))
os.system('hdiutil attach -readwrite -noverify -noautoopen %s.dmg' % NAME)
os.mkdir('/Volumes/%s/.background' % NAME)
image.save('/Volumes/%s/.background/background.png' % NAME, 'PNG')
apple_script = """osascript<<END
tell application "Finder"
tell disk "%s"
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {{100, 100, 355, 355}}
set theViewOptions to the icon view options of container window
set the background picture of theViewOptions to file ".background:background.png"
close
open
end tell
end tell
END""" % NAME
os.system(apple_script)
If run, the background will get correctly set in the disk image called 'works', and not in the one called 'doesnotwork'. It seems that I am limited to 5 characters for the volume name. However, if I shorten the name of the folder use to store the background, e.g. to .bkg instead of .background, then I can use a longer volume name, which suggests this is an issue related to the length of the overall path. Does anyone know at what level there is a limit on the path length? Is there a workaround to allow arbitrarily long paths?
EDIT: I am using MacOS 10.6 - the script seems to work correctly on 10.7

I believe you have to escape your quotes. You can't have quotes inside of quotes without escaping them. For example it should be, tell application \"Finder\". You have many places where your quotes are not used properly. If you look at the example script you linked to that person used single and double quotes cleverly to avoid this issue. My suggestion is you fix that.
Plus you can't refer to a file in applescript like this... ".background:background.png". Applescript doesn't know what that means when a path begins with a period. A path in applescript begins with the name of the hard drive like Macintosh HD. You need to put the whole path there in a proper applescript format. And that needs to be quoted too with escaped quotes.
Good luck.

Related

pyautocad - automate drawing - import DWG - write text - import image

i'm not a professional coder and i'm so sorry for my english :)
i hope you understand.
I'm trying to automate part of my job.
i have to create dwg; every layer for me is a sheet (like A4 paper), for that reason i have to change layer and import specific dwg/dxf from my repository symbol.
For example i have to:
(start new project)
open newproject.dwg
(paste dwg)
import C:\repository_cad\symbol1.dwg in layer n°3 with coordinate X 100 Y 200.
(write text in the middle of symbol)
write "SYMBOL_1" layer n°3 coordinate X 150 Y200 alignment center.
(insert logo image)
import C:\repository_cad\image1.jpg in coordinate X 10 Y 20
i'm trying to use pyautocad, but i cant find a command for import dxf, and i dont find information about changing layer.
i find out only the command for draw the line, circle ecc, but if i have to re-draw all my repository by python i need to much time, i hope is possible copy draw from another dwg and paste it in my new dwg.
can someone give to me a little help with these 3 command?
maybe is not possible making this stuff on pyautocad? is there other library for python?
i read the docs but i dont see info about some import function.
so, i tried:
from pyautocad import Autocad, APoint
acad = Autocad(create_if_not_exists=False)
acad.prompt("Hello, Autocad from Python\n")
print (acad.doc.Name)
and it's works, on autocad terminal i can see "Hello, Autocad from Python"
in the Docs i find out how write a autocad-command from python.
The function is:
prompt()
i tried:
acad.prompt('-INSERT') #-INSERT is the autocad command for import dxf or dwg
acad.prompt('C:\SPAC\Librerie\Elettr\02-15-04.dwg')#this is the path of the cad
acad.prompt('-15 -15') #coord X Y of the point where i want to paste
acad.prompt('1') # 1 is the scale factor in X
acad.prompt('1') # 1 is the scale factor in Y (autocad askt first in X and after in Y
acad.prompt('0') #degree of rotation
at this point i havent error on python and no error on autocad terminal, but the draw not appear on cad
thanks
Max
acad.prompt() will just echo the string to the command line. What you are looking for is acad.doc.SendCommand(), e.g.
acad.doc.SendCommand('-INSERT ')
Notice there is a blank space after the autocad command, that stands for to activate the command.

Increase graph size in plantUML from python?

MWE
To generate PlantUML diagrams in (sub)folder: /Diagrams/ I use the following python script:
from plantuml import PlantUML
import os
from os.path import abspath
from shutil import copyfile
os.environ['PLANTUML_LIMIT_SIZE'] = str(4096 * 4) # set max with to 4 times the default (16,384)
server = PlantUML(url='http://www.plantuml.com/plantuml/img/',
basic_auth={},
form_auth={}, http_opts={}, request_opts={})
diagram_dir = "./Diagrams"
#directory = os.fsencode()
for file in os.listdir(diagram_dir):
filename = os.fsdecode(file)
if filename.endswith(".txt"):
server.processes_file(abspath(f'./Diagrams/{filename}'))
It is used to generate for example the following test.txt file:
#startuml
'Enforce straight lines
skinparam linetype ortho
' Set direction of graph hierarchy
Left to Right direction
' create work package data
rectangle "something something something" as ffd0
rectangle "something something something" as ffd1
rectangle "something something something something something" as ffd2
rectangle "something something something something" as ffd3
rectangle "something something somethingsomethingsomething" as ffd4
rectangle "something something something something something something" as ffd5
rectangle "something something something something" as ffd6
rectangle "something something something " as ffd7
' Implement graph hierarchy
ffd0-->ffd1
ffd1-->ffd2
ffd2-->ffd3
ffd3-->ffd4
ffd4-->ffd5
ffd5-->ffd6
ffd6-->ffd7
#enduml
Expected behavior
Because I set the PLANTUML_LIMIT_SIZE variable to 16384 (pixels) as the FAQ suggests, I would expect this to fill up the picture of the diagram with all the blocks connected side by side up to a max width of 4096 * 4 pixels.
To test whether perhaps setting it from the python script was implemented incorrectly I also tried to set it manually with: set PLANTUML_LIMIT_SIZE=16384 to expect the same behavior as explained in the above paragraph (a picture filled up till 16384 pixels).
Observed behavior
Instead PlantUML cuts off the picture at 2000 horizontal pictures as shown in the figure below:
Question
How can I ensure the PlantUML does not cut off the blocks of the diagrams of n pixels (height or width), from a python script?
The best way I've found to prevent diagrams from being cut off, without trying to guess at the size or picking some arbitrarily large limit, is to select SVG output.
Note that setting PLANTUML_LIMIT_SIZE is only going to have an effect if you're running PlantUML locally, but it appears the Python interface you're using sends the diagram to the online service. I don't know the internals of that interface, but per the documentation you should be able to get SVG output by using http://www.plantuml.com/plantuml/svg/ as the service URL.
If you need the final image in PNG format, you will need to convert it with another tool.
Approach 1:
To prevent the diagram from being cut off I followed the following steps:
Downloaded the plantuml.jar from this location http://sourceforge.net/projects/plantuml/files/plantuml.jar/download
Put the diagram which I wrote in a someLargeDiagram.txt file, in the same directory as the plantuml.jar file.
Opened terminal on Ubuntu 20.04 in that same directory and ran:
java -jar plantuml.jar -verbose someLargeDiagram.txt
That successfully generated the diagram as .png file, which was not cut off.
Approach 2:
After creating even larger graphs, they got cut-off again, and it gave the message to increase the PLANTUML_LIMIT_SIZE. I tried passing the size as an argument in the commandline using: java -jar plantuml.jar -verbose -PLANTUML_LIMIT_SIZE=8192 Diagrams/latest.uml however that did not work, nor did ..-PLANTUML_LIMIT_SIZE 8192... This link suggested one could set it as an environment variable, so I did that in Ubuntu 20.04 using command: export PLANTUML_LIMIT_SIZE 8192, after which I successfully created a larger diagram that was not cut-off with command:
java -jar plantuml.jar -verbose Diagrams/latest.uml

python ghostscript not closing output file

I'm trying to turn PDF files with one or many pages into images for each page. This is very much like the question found here. In fact, I'm trying to use the code from #Idan Yacobi in that post to accomplish this. His code looks like this:
import ghostscript
def pdf2jpeg(pdf_input_path, jpeg_output_path):
args = ["pdf2jpeg", # actual value doesn't matter
"-dNOPAUSE",
"-sDEVICE=jpeg",
"-r144",
"-sOutputFile=" + jpeg_output_path,
pdf_input_path]
ghostscript.Ghostscript(*args)
When I run the code I get the following output from python:
##### 238647312 c_void_p(238647312L)
When I look at the folder where the new .jpg image is supposed to be created, there is a file there with the new name. However, when I attempt to open the file, the image preview says "Windows Photo Viewer can't open this picture because the picture is being edited in another program."
It seems that for some reason Ghostscript opened the file and wrote to it, but didn't close it after it was done. Is there any way I can force that to happen? Or, am I missing something else?
I already tried changing the last line above to the code below to explicitly close ghostscript after it was done.
GS = ghostscript.Ghostscript(*args)
GS.exit()
I was having the same problem where the image files were kept open but when I looked into the ghostscript init.py file (found in the following directory: PythonDirectory\Lib\site-packages\ghostscript__init__.py), the exit method has a line commented.
The gs.exit(self._instance) line is commented by default but when you uncomment the line, the image files are being closed.
def exit(self):
global __instance__
if self._initialized:
print '#####', self._instance.value, __instance__
if __instance__:
gs.exit(self._instance) # uncomment this line
self._instance = None
self._initialized = False
I was having this same problem while batching a large number of pdfs, and I believe I've isolated the problem to an issue with the python bindings for Ghostscript, in that like you said, the image file is not properly closed. To bypass this, I had to go to using an os system call. so given your example, the function and call would be replaced with:
os.system("gs -dNOPAUSE -sDEVICE=jpeg -r144 -sOutputFile=" + jpeg_output_path + ' ' + pdf_input_path)
You may need to change "gs" to "gswin32c" or "gswin64c" depending on your operating system. This may not be the most elegant solution, but it fixed the problem on my end.
My work around was actually just to install an image printer and have Python print the PDF using the image printer instead, thus creating the desired jpeg image. Here's the code I used:
import win32api
def pdf_to_jpg(pdf_path):
"""
Turn pdf into jpg image(s) using jpg printer
:param pdf_path: Path of the PDF file to be converted
"""
# print pdf to jpg using jpg printer
tempprinter = "ImagePrinter Pro"
printer = '"%s"' % tempprinter
win32api.ShellExecute(0, "printto", pdf_path, printer, ".", 0)
I was having the same problem when running into a password protected PDF - ghostscript would crash and not close the PDF preventing me from deleting the PDF.
Kishan's solution was already applied for me and therefore it wouldn't help my problem.
I fixed it by importing GhostscriptError and instantiating an empty Ghostscript before a try/finally block like so:
from ghostscript import GhostscriptError
from ghostscript import Ghostscript
...
# in my decryptPDF function
GS = Ghostscript()
try:
GS = Ghostscript(*args)
finally:
GS.exit()
...
# in my function that runs decryptPDF function
try:
if PDFencrypted(append_file_path):
decryptPDF(append_file_path)
except GhostscriptError:
remove(append_file_path)
# more code to log and handle the skipped file
...
For those that stumble upon this with the same problem. I looked through the python ghostscript init file and discovered the ghostscript.cleanup() function/def.
Therefore, I was able to solve the problem by adding this simple one-liner to the end of my script [or the end of the loop].
ghostscript.cleanup()
Hope it helps someone else because it frustrated me for quite a while.

Non-Ubuntu oriented pygame platformer not loading levels correctly on anything other than Ubuntu

I've been working on a pygame platformer, based on this. I wrote it on an Ubuntu machine, and it doesn't seem to work on other operating systems.
The generation code is something like this:
levelFile = tkFileDialog.askopenfile(mode='r', defaultextension='.lvl', filetypes=[('Level File', '*.lvl')], parent=tk)
level = levelFile.read().split("\n")
del level[len(level) - 1]
# Add platforms to array based on level string
I made a level in a text editor using ASCII characters to represent different tiles.
It works fine on my Ubuntu machine, but when run on a MacBook Air and a Windows laptop, it doesn't. The level layout doesn't load as expected (the tiles load in unexpected places, and the camera position is messed up).
Does anyone have any idea what is going on and how to fix it?
The line separators in your level file are OS-dependent if you create your file under linux it will use "\n" under windows "\r\n", so this could be a reason why it is not working. i think you should use os.linesep instead of "\n" to split the file into lines.
level = levelFile.read().split(os.linesep)

Gimp: How to export an image to BMP without the color space information using a python script?

I'm writing a python script for Gimp to export all the layers of an image to BMPs.
To export a given layer, I use the procedure file_bmp_save:
pdb.file_bmp_save(image, layer, filename, raw_filename)
But this function save the color space information in the BMP header.
When I export BMP manually (File > Export), there is an option
do not write color space information
See screen capture
I would like to reproduce this option in my python script.
So - I went to check it, and indeed - this option is not available programatically at all.
The case is the chunk that is named as "color space information" on GIMP BMP export filter is actually the binary difference between a version 3 BMP file, and a version 4 bmp file, which was introduced as far back as Windows 95.
So, I beg you to rethink where you are using BMP files that need file versions as old as Pre-windows 95 files.
That said, at some point, someone with GIMP hacking capabilities felt that need, and added the option for these v3 files to the export GUI - but the same person did not bother adding a second PDB call for PDB save: the file_bmp_save call itself could not be changed to have the extra "dont_write_color_information" parameter - GIMP PDB calls are kept backwards compatible across major GIMP versions (which is like forever). And adding a second procedure circa 2004, 2005 to support saving a file version obsoleted in 1995, would be counterproductive.
Fortunatelly, it is just a matter of 68 bytes that are written at the end of the V4 header - and the different offsets are recorded in jus 3 points in the file. Therefore, it is easy to write a Python solution for converting these files to the format you need.
Should the conversion be more complicated, the path there would be to: file a bug with GIMP project so that a programmatic call could be made for the GUI exiting option, (and preferably code the patch for that and attach it to the bug, since GIMP is a volunteer only project) and wait for a new version of GIMP featuring the change. In the meantime, use an workaround with an external program which could make the needed image conversion (or your own patched version of GIMP).
As it is, though, the following Python function will convert the BMP version after it is exported by GIMP:
import struct
V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF = 2
def strip_color_info(old_bmp_name, new_bmp_name=None):
if new_bmp_name is None:
new_bmp_name = old_bmp_name
data = bytearray(open(old_bmp_name, "rb").read())
header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
if header_size == 108:
# Remove 68 - the size for the extra data-chunk from both headers
data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
# Offset image data:
data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] = data[HEADER_OFF + header_size:]
data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
with open(new_bmp_name, "wb") as output_file:
output_file.write(data)
(disclaimer: I've just tested this with an RGB 24bpp file - though it should work for other formats as well)

Categories

Resources