Permission denied error when writing to transient filepath

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Permission denied error when writing to transient filepath

Post by Joel_graff »

So I'm trying to write to a transient file in FreeCAD. Unfortunately, when I try to open it for writing with the following code:

Code: Select all

>>> with open(App.ActiveDocument.TransientDir + '/alignment.xml', 'w', encoding='UTF-8') as _f:
... 	print(_f)
... 
I get the error:

Code: Select all

Traceback (most recent call last):
  File "<input>", line 1, in <module>
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\GRAFFJC\\AppData\\Local\\Temp\\FreeCAD_Doc_cfdd3cb9-5e3f-48c6-b645-105141669846_a1475c_5068/alignment.xml'
I've checked and I have full permissions to the file under my username, so I'm a bit perplexed as to why this is happening. I've successfully done this before, so it must a change I made, but I don't know what else would cause that error.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
Syres
Veteran
Posts: 2898
Joined: Thu Aug 09, 2018 11:14 am

Re: Permission denied error when writing to transient filepath

Post by Syres »

Is there not a filename.LOCK file in the TEMP folder from an old process that didn't close cleanly in the recent past, hence giving the permission denied error?
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Permission denied error when writing to transient filepath

Post by Joel_graff »

Syres wrote: Wed Apr 17, 2019 3:37 pm Is there not a filename.LOCK file in the TEMP folder from an old process that didn't close cleanly in the recent past, hence giving the permission denied error?
The only lock file I see is 'FreeCAD_5068.lock' in the parent folder. In the transient folder the only file that is there is the file I'm trying to overwrite.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Permission denied error when writing to transient filepath

Post by Joel_graff »

So here's an example FeaturePython class that demonstrates the error.

I'm trying to write to the XML in the onDocumentRestored event. Maybe that's not allowed? Nevertheless, I get the same error if I try to open the file for writing from the FreeCAD python console, or even the python console launched from a terminal window.

I get the error following the steps below in the Python console:

1. Call create()
2. Save the file
3. Close the file, then reopen it.

Notes:
- Step 1 should create 'my_file.txt' in the user home directory
- Step 3 tries to write to the transient file location, which triggers the 'Permission Denied' error.

Code: Select all

import datetime
import FreeCAD as App

def create():
	
    file_path = App.getHomePath() + 'my_file.txt'
    
    with open(file_path, ''w', encoding='UTF-8') as _f:

        _f.write('Initial write at ' + str(datetime.datetime.now()))

    obj = App.ActiveDocument.addObject("App::FeaturePython", 'TransientFpo')
    fpo = TransientFpo(obj)

    obj.filepath = file_path

class TransientFpo():

    def __init__(self, obj):
        """
        Default Constructor
        """
        obj.Proxy = self
        self.Type = "TransientFpo"
        self.Object = obj

        obj.addProperty(
            'App::PropertyFileIncluded', 'filepath', '').filepath = ''

        self.init = True

    def __getstate__(self):
        return self.Type

    def __setstate__(self, state):
        if state:
            self.Type = state

    def onDocumentRestored(self, obj):

        with open(App.ActiveDocument.TransientDir + '/my_file.txt', 'w', encoding='UTF-8') as _f:
            _f.write('updated at ' + str(datetime.datetime.now()))
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Permission denied error when writing to transient filepath

Post by wmayer »

So here's an example FeaturePython class that demonstrates the error.
With your code snippet I can reproduce this problem.

I don't know how it happens but the file my_file.txt inside the transient directory is marked as read-only. But when I extract the file my_file.txt from the zip file then it is not marked as read-only. So, at some point during the restore the file attribute must be changed.

EDIT:
It's the assignment to the property that changes the file attribute.

Code: Select all

import datetime

doc=App.ActiveDocument
obj=doc.addObject("App::FeaturePython","Feature")
obj.addProperty("App::PropertyFileIncluded","File")
with open(App.ActiveDocument.TransientDir + '/alignment.xml', 'w', encoding='UTF-8') as _f:
    _f.write('initialized at ' + str(datetime.datetime.now()))

# after this the file is read-only
obj.File=doc.TransientDir+"/alignment.xml"

# raises a permission error
with open(App.ActiveDocument.TransientDir + '/alignment.xml', 'w', encoding='UTF-8') as _f:
    _f.write('updated at ' + str(datetime.datetime.now()))
For more details see: https://github.com/FreeCAD/FreeCAD/blob ... e.cpp#L181

So, as soon as a file is assigned to a property of a feature it's marked read-only to make the undo/redo working and that nobody unauthorized modifies it.

So, if you are sure about what you do you can remove the write-protection, write to it and restore the protection afterwards.
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Permission denied error when writing to transient filepath

Post by Joel_graff »

wmayer wrote: Tue May 28, 2019 1:34 pm So, if you are sure about what you do you can remove the write-protection, write to it and restore the protection afterwards.
Hmmm... os.chmod() looks like it will do it. According to the Python docs, Windows will honor stat.S_IWRITE and stat.S_IREAD, which controls user-level read / write permissions... I think. :)

Thanks!
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
Post Reply