Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: module 'os' has no attribute 'link'. Did you mean: 'unlink'? #406

Open
vzool opened this issue Feb 20, 2025 · 3 comments
Open

Comments

@vzool
Copy link

vzool commented Feb 20, 2025

BUG

What I did:

import ZODB # just import & run

What I expect to happen:

Run without errors

What actually happened:

Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 15, in <module>
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/ZODB/__init__.py", line 21, in <module>
    from ZODB.DB import DB
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/ZODB/DB.py", line 33, in <module>
    from ZODB.Connection import Connection
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/ZODB/Connection.py", line 35, in <module>
    from ZODB.blob import SAVEPOINT_SUFFIX
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/ZODB/blob.py", line 950, in <module>
    link_or_copy = os.link
                   ^^^^^^^
AttributeError: module 'os' has no attribute 'link'. Did you mean: 'unlink'?

[Program finished]

What version of Python and Zope/Addons I am using:

Python: 3.11.4
Zope/Addons: None
Platform: Android 13 Arm64
Application: Pydroid 3

@icemac
Copy link
Member

icemac commented Feb 21, 2025

Android 13 is not officially supported by ZODB.

Are you sure you have a complete Python installation on your device?
According to https://docs.python.org/3/library/os.html#os.link os.link should exist on any Unix or Windows.

The failing code is in

ZODB/src/ZODB/blob.py

Lines 931 to 950 in 783610f

if sys.platform == 'win32':
# On Windows, you can't remove read-only files, so make the
# file writable first.
def remove_committed(filename):
os.chmod(filename, stat.S_IWRITE)
os.remove(filename)
def remove_committed_dir(path):
for (dirpath, dirnames, filenames) in os.walk(path):
for filename in filenames:
filename = os.path.join(dirpath, filename)
remove_committed(filename)
shutil.rmtree(path)
link_or_copy = shutil.copy
else:
remove_committed = os.remove
remove_committed_dir = shutil.rmtree
link_or_copy = os.link

Here different options are set for different OS.
To be successfull you need either os.link or at least shutil.copy, so try to modify the code to use the latter one and report back your findings.

@vzool
Copy link
Author

vzool commented Feb 22, 2025

According to this solution pyodide/pyodide#3880 (comment), I could resolve the issue by the following hack:

# --- <hack>
import os
print(hasattr(os, 'link')) # --> False
os.link = os.symlink
print(hasattr(os, 'link')) # --> True
# --- </hack>
import ZODB # just import & run
# imported successfully

@vzool
Copy link
Author

vzool commented Feb 22, 2025

I just hit another error:

False
True
Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/zc/lockfile/__init__.py", line 60, in _lock_file
    fcntl.flock(file.fileno(), _flags)
OSError: [Errno 38] Function not implemented

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 25, in <module>
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/ZODB/FileStorage/FileStorage.py", line 251, in __init__
    self._lock_file = LockFile(file_name + '.lock')
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/zc/lockfile/__init__.py", line 120, in __init__
    super().__init__(path)
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/zc/lockfile/__init__.py", line 93, in __init__
    _lock_file(fp)
  File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/zc/lockfile/__init__.py", line 62, in _lock_file
    raise LockError("Couldn't lock %r" % file.name)
zc.lockfile.LockError: Couldn't lock 'mydata.fs.lock'

[Program finished]

The Code

import persistent

class Account(persistent.Persistent):

    def __init__(self):
        self.balance = 0.0

    def deposit(self, amount):
        self.balance += amount

    def cash(self, amount):
        assert amount < self.balance
        self.balance -= amount
 
# --- <hack>
import os
print(hasattr(os, 'link')) # --> False
os.link = os.symlink
print(hasattr(os, 'link')) # --> True
# --- </hack>
import ZODB # just import & run
# imported successfully

import ZODB.FileStorage
storage = ZODB.FileStorage.FileStorage('mydata.fs')
db = ZODB.DB(storage)
connection = db.open()
root = connection.root

import BTrees._OOBTree
root.accounts = BTrees.OOBTree.BTree()
root.accounts['account-1'] = Account()
root.accounts['account-1'].deposit(9630)

import transaction
transaction.commit()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants