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

wrap atomic_write preserving permissions of mets.xml #625

Merged
merged 4 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ocrd/ocrd/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import cv2
from PIL import Image
import numpy as np
from atomicwrites import atomic_write
from deprecated.sphinx import deprecated

from ocrd_models import OcrdMets, OcrdExif, OcrdFile
from ocrd_models.ocrd_page import parse
from ocrd_utils import (
atomic_write,
getLogger,
image_from_polygon,
coordinates_of_segment,
Expand Down Expand Up @@ -252,7 +252,7 @@ def save_mets(self):
log.info("Saving mets '%s'", self.mets_target)
if self.automatic_backup:
WorkspaceBackupManager(self).add()
with atomic_write(self.mets_target, overwrite=True) as f:
with atomic_write(self.mets_target) as f:
f.write(self.mets.to_xml(xmllint=True).decode('utf-8'))

def resolve_image_exif(self, image_url):
Expand Down
6 changes: 2 additions & 4 deletions ocrd/ocrd/workspace_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import hashlib

from ocrd_models import OcrdMets
from ocrd_utils import getLogger
from ocrd_utils import getLogger, atomic_write

from .constants import BACKUP_DIR

from atomicwrites import atomic_write

def _chksum(s):
return hashlib.sha256(s).hexdigest()

Expand Down Expand Up @@ -85,7 +83,7 @@ def add(self):
mets_file = join(d, 'mets.xml')
log.info("Backing up to %s" % mets_file)
makedirs(d)
with atomic_write(mets_file, overwrite=True) as f:
with atomic_write(mets_file) as f:
f.write(mets_str.decode('utf-8'))
return chksum

Expand Down
1 change: 0 additions & 1 deletion ocrd/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ opencv-python-headless
Flask
jsonschema
pyyaml
atomicwrites >= 1.3.0
Deprecated == 1.2.0
1 change: 1 addition & 0 deletions ocrd_utils/ocrd_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@

from .os import (
abspath,
atomic_write,
pushd_popd,
unzip_file_to_dir)

Expand Down
29 changes: 26 additions & 3 deletions ocrd_utils/ocrd_utils/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
'abspath',
'pushd_popd',
'unzip_file_to_dir',
'atomic_write',
]

from atomicwrites import atomic_write as atomic_write_, AtomicWriter
from tempfile import TemporaryDirectory
import contextlib
from os import getcwd, chdir
import os.path
from os import getcwd, chdir, stat, fchmod, umask
from os.path import exists, abspath as abspath_

from zipfile import ZipFile

Expand All @@ -22,7 +24,7 @@ def abspath(url):
"""
if url.startswith('file://'):
url = url[len('file://'):]
return os.path.abspath(url)
return abspath_(url)

@contextlib.contextmanager
def pushd_popd(newcwd=None, tempdir=False):
Expand Down Expand Up @@ -54,3 +56,24 @@ def unzip_file_to_dir(path_to_zip, output_directory):
z.close()



# ht @pabs3
# https://github.com/untitaker/python-atomicwrites/issues/42
class AtomicWriterPerms(AtomicWriter):
def get_fileobject(self, **kwargs):
f = super().get_fileobject(**kwargs)
try:
mode = stat(self._path).st_mode
except FileNotFoundError:
# Creating a new file, emulate what os.open() does
mask = umask(0)
umask(mask)
mode = 0o664 & ~mask
fd = f.fileno()
fchmod(fd, mode)
return f

@contextlib.contextmanager
def atomic_write(fpath):
with atomic_write_(fpath, writer_cls=AtomicWriterPerms, overwrite=True) as f:
yield f
1 change: 1 addition & 0 deletions ocrd_utils/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ Pillow >= 7.2.0
# All current versions of TensorFlow require numpy < 1.19.0,
# so make sure that now newer version is installed here.
numpy >= 1.17.0, < 1.19.0
atomicwrites >= 1.3.0
19 changes: 17 additions & 2 deletions tests/test_workspace.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from os import walk
from os import walk, stat, chmod, umask
from stat import filemode
from subprocess import run, PIPE
from os.path import join, exists, abspath, basename, dirname
from tempfile import TemporaryDirectory, mkdtemp
Expand All @@ -10,7 +11,7 @@
from tests.base import TestCase, assets, main, copy_of_directory

from ocrd_models.ocrd_page import parseString
from ocrd_utils import pushd_popd
from ocrd_utils import pushd_popd, initLogging
from ocrd.resolver import Resolver
from ocrd.workspace import Workspace

Expand Down Expand Up @@ -278,6 +279,20 @@ def test_image_from_page_basic(self):
img, info, exif = ws.image_from_page(pcgts.get_Page(), page_id='PHYS_0017')
self.assertEquals(info['features'], 'binarized,clipped')

def test_mets_permissions(self):
with TemporaryDirectory() as tempdir:
ws = self.resolver.workspace_from_nothing(tempdir)
ws.save_mets()
mets_path = join(ws.directory, 'mets.xml')
mask = umask(0)
umask(mask)
assert (stat(mets_path).st_mode) == 0o100664 & ~mask
chmod(mets_path, 0o777)
ws.save_mets()
assert filemode(stat(mets_path).st_mode) == '-rwxrwxrwx'




if __name__ == '__main__':
main(__file__)