Closed darioclock closed 3 months ago
Solution appears to be to to add Metadata/Properties.plist
to the new zipfile. Can you test that this works: unzip the newly saved file, create Metadata/Properties.plist
using the following content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>fileFormatVersion</key>
<string>13.2.1</string>
<false/>
</dict>
</plist>
And then re-zip. With an empty document this worked for me. If this works in your example then it's easy enough to re-generate the missing file on save. I'm also wondering whether document images are preserved?
Thanks for the quick reply!
My file is in zip format and already contains the Metadata/Properties.plist
Here is what's inside:
// !!! BINARY PROPERTY LIST WARNING !!!
//
// The pretty-printed property list below has been created
// from a binary version on disk and should not be saved as
// the ASCII format is a subset of the binary representation!
//
{ documentUUID = "somenumbers";
fileFormatVersion = "13.2.1";
isMultiPage = :false;
privateUUID = "somenumbers";
revision = "somenumbers";
shareUUID = "somenumbers";
stableDocumentUUID = "somenumbers";
versionUUID = "somenumbers";
}
which seems pretty different from what you are suggesting to replace it with.
This is the traceback from the issue:
Traceback (most recent call last):
File "/Users/.../test.py", line 153, in <module>
source_doc.save(source_path)
File "/Users/.../.pyenv/versions/3.9.6/lib/python3.9/site-packages/numbers_parser/document.py", line 143, in save
write_numbers_file(filename, self._model.file_store)
File "/Users/.../.pyenv/versions/3.9.6/lib/python3.9/site-packages/numbers_parser/file.py", line 60, in write_numbers_file
zipf = ZipFile(filename, "w")
File "/Users/.../.pyenv/versions/3.9.6/lib/python3.9/zipfile.py", line 1239, in __init__
self.fp = io.open(file, filemode)
IsADirectoryError: [Errno 21] Is a directory: '/Users/.../myfileinzipformat.numbers'
It's failing the save because the file.numbers is now considered a directory when in package format. It's weird that opening and loading the document works without issue but the saving fails.
It’s weird cause it seems ZipFile seems to accept a path as an input. I’ll look at their code next if it’s open.
I believe this is fixed in v4.9.0.
Mmh, I get the same error in 4.9.1. With same traceback (sorry I closed the issue by mistake).
The same traceback? I installed into a new environment and I can't reproduce the exception. I do get a corrupted Numbers file though (fails to open).
v4.9.3 includes fixed support.
I'm really sorry to be the bearer of bad news. Even with 4.9.3 I still fails at the same step. I tired with Python 3.9.6 and 3.10.5.
The creation of the ZipFile
class in write_numbers_file
fails because the path that I provide /my/path/to/file.numbers
is identified as a directory when the file is in "Package" mode.
Please keep in mind that in my example I'm opening an already existing document that already is in "Package" mode and then I'm modifying it and intending to save it with the same name.
Oh you're trying to overwrite the folder? That won't work -- you will need to write to a different location. I don't plan to support writing the package format.
Understood, thanks for the support.
For completion, here is the reason why I need to overwrite the document and can't create a new one.
I tried using other sharing strategies like "Box" that allow to keep the numbers file in a "Single File" mode but I had multiple bugs/issues with the UI. Doesn't work great for live collaboration. The only solution that I see at this point is to use AppleScript to do the mods that I need.
I see. It's a more significant change to support package mode for writes. It needs some thought about how to convert single-file to package versus overwriting existing packages. I'll take a look but it'll not be this weekend.
Thank you very much for the support.
In v4.10.0 Document.save()
now takes an additional package
argument that will write a folder-based package. It will refuse to do so if the target is a file or if the target looks malformed.
The file IO has been extensively rewritten but tests to full coverage and I've added more exception checking and sanity checking, so things should be sound. I'd certainly keep copies of documents though in case something bad happens when overwriting. I keep my checked out git repos in iCloud and occasionally Apple's synchronisation throws a bit of a wobbly.
Thank you very much! I'll give it a try as soon as possible, but it might not be this weekend.
Hi!
I gave it a quick try and it seems it works as expected! It seems it also maintains the "Sharing" features when sharing with iCloud but I wanna check-in with my colleagues and see if everything is ok on their end too.
I noticed that I had to run my script twice for the mods to appear. The first time the mods didn't take place at all. Not sure why that was the case but it could be because of iCloud. I will test more thoroughly as I have more chances to run it.
I'd wait to test more before closing the issue.
Thank you again!
Hi,
I have tried this feature for the past week and it seems to work great!
With this I can programmatically edit a file that is shared in iCloud without affecting the access that other people already have on the file.
A Numbers file can either be in "Package" mode or "Single File" mode. One can choose the format of the file by going to File -> Advanced -> Change File Type. When the file is in Package mode, the document can be opened and read but it can't be saved.
To Reproduce from numbers_parser import Document doc_path = "./doc_in_package_mode.numbers" doc = Document(doc_path) doc.save(doc_path)
Expected behavior I expect the file to be saved.