Skip to content

Commit

Permalink
Merge ea899eb into cfa0c96
Browse files Browse the repository at this point in the history
  • Loading branch information
jacebrowning committed Jan 30, 2021
2 parents cfa0c96 + ea899eb commit 739645e
Show file tree
Hide file tree
Showing 13 changed files with 21 additions and 111 deletions.
2 changes: 2 additions & 0 deletions datafiles/settings.py
Expand Up @@ -9,3 +9,5 @@
MINIMIZE_LIST_DIFFS = True

YAML_LIBRARY = 'ruamel.yaml'

WRITE_DELAY = 0.0 # seconds
3 changes: 3 additions & 0 deletions datafiles/utils.py
@@ -1,6 +1,7 @@
"""Internal helper functions."""

import dataclasses
import time
from contextlib import suppress
from functools import lru_cache
from pathlib import Path
Expand All @@ -10,6 +11,7 @@

import log

from . import settings
from .types import Missing


Expand Down Expand Up @@ -114,6 +116,7 @@ def write(filename_or_path: Union[str, Path], text: str, *, display=False) -> No

path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text)
time.sleep(settings.WRITE_DELAY) # ensure the file modification time changes


def read(filename: str, *, display=False) -> str:
Expand Down
12 changes: 12 additions & 0 deletions docs/settings.md
Expand Up @@ -80,3 +80,15 @@ This setting controls the underlying YAML library used to read and write files.

- `'ruamel.yaml'` (default)
- `'PyYAML'`

# `WRITE_DELAY`

One some file systems, the modification time of a file ([`st_mtime`](https://docs.python.org/3/library/os.html#os.stat_result.st_mtime)) is unchanged if a file is read immediately after writing. This may cause intermittent issues if your use case involves rapidly changing files.

To compensate for this, a short delay can be inserted after `datafiles` writes to the file system:

```python
import datafiles

datafiles.settings.WRITE_DELAY = 0.01 # seconds
```
74 changes: 1 addition & 73 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
@@ -1,7 +1,7 @@
[tool.poetry]

name = "datafiles"
version = "0.12b3"
version = "0.12b4"
description = "File-based ORM for dataclasses."

license = "MIT"
Expand Down Expand Up @@ -66,7 +66,7 @@ isort = "=5.5.1"

# Linters
mypy = "~0.790"
pylint = { git = "https://github.com/PyCQA/pylint", branch = "master" }
pylint = "~2.6.0"
pydocstyle = "*"

# Testing
Expand Down
3 changes: 0 additions & 3 deletions pytest.ini
Expand Up @@ -15,9 +15,6 @@ cache_dir = .cache
log_level = DEBUG
log_format = %(relpath)s:%(lineno)-4d %(levelname)5s: %(message)s

markers =
flaky

[pytest-watch]

ignore =.cache,htmlcov,tml
Expand Down
12 changes: 1 addition & 11 deletions tests/conftest.py
@@ -1,4 +1,3 @@
import os
from pathlib import Path
from shutil import rmtree

Expand All @@ -9,9 +8,7 @@


settings.HIDE_TRACEBACK_IN_HOOKS = False


xfail_on_ci = pytest.mark.xfail(bool(os.getenv('CI')), reason="Flaky on CI")
settings.WRITE_DELAY = 0.1


def pytest_configure(config):
Expand All @@ -20,13 +17,6 @@ def pytest_configure(config):
log.init() # TODO: determine why the 'relpath' filter wasn't added automatically


def pytest_collection_modifyitems(items):
for item in items:
for marker in item.iter_markers():
if marker.name == 'flaky':
item.add_marker(xfail_on_ci)


@pytest.fixture(autouse=True)
def create_tmp():
path = Path('tmp')
Expand Down
7 changes: 0 additions & 7 deletions tests/test_automatic_attributes.py
@@ -1,8 +1,6 @@
# pylint: disable=unused-variable


import pytest

from datafiles import datafile
from datafiles.utils import logbreak

Expand All @@ -13,7 +11,6 @@ class Sample:


def describe_auto_attr():
@pytest.mark.flaky
def with_builtin(expect):
sample = Sample('abc')

Expand All @@ -28,7 +25,6 @@ def with_builtin(expect):
logbreak("Getting attribute")
expect(sample.count) == 4

@pytest.mark.flaky
def with_empty_list(expect):
sample = Sample('abc')

Expand All @@ -44,7 +40,6 @@ def with_empty_list(expect):
logbreak("Getting attribute")
expect(sample.empty_items) == [4.2, "abc"]

@pytest.mark.flaky
def with_homogeneous_list(expect):
sample = Sample('abc')

Expand All @@ -59,7 +54,6 @@ def with_homogeneous_list(expect):
logbreak("Getting attribute")
expect(sample.same_items) == [1, 2, 3]

@pytest.mark.flaky
def with_heterogeneous_list(expect):
sample = Sample('abc')

Expand All @@ -74,7 +68,6 @@ def with_heterogeneous_list(expect):
logbreak("Getting attribute")
expect(sample.mixed_items) == [1, "abc", 3.2]

@pytest.mark.flaky
def with_dict(expect):
sample = Sample('abc')

Expand Down
6 changes: 0 additions & 6 deletions tests/test_custom_converters.py
Expand Up @@ -2,8 +2,6 @@

from datetime import datetime

import pytest

from datafiles import Missing, converters, datafile


Expand Down Expand Up @@ -31,7 +29,6 @@ def to_python_value(cls, deserialized_data, **_kwargs):
return datetime.fromisoformat(deserialized_data)


@pytest.mark.flaky
def test_extension(expect):
@datafile("../tmp/sample.yml")
class Timestamp:
Expand All @@ -47,7 +44,6 @@ class Timestamp:
expect(ts.dt.day) == 11


@pytest.mark.flaky
def test_extension_with_default(expect):
@datafile("../tmp/sample.yml")
class Timestamp:
Expand All @@ -63,7 +59,6 @@ class Timestamp:
expect(ts.dt.day) == 11


@pytest.mark.flaky
def test_registration(expect):

converters.register(datetime, DateTimeConverter)
Expand All @@ -82,7 +77,6 @@ class Timestamp:
expect(ts.dt.day) == 22


@pytest.mark.flaky
def test_registration_with_default(expect):

converters.register(datetime, DateTimeConverter)
Expand Down
1 change: 0 additions & 1 deletion tests/test_custom_converters_future.py
Expand Up @@ -11,7 +11,6 @@
from .test_custom_converters import MyDateTime


@pytest.mark.flaky
def test_extension(expect):
@datafile("../tmp/sample.yml")
class MyObject:
Expand Down
2 changes: 0 additions & 2 deletions tests/test_extended_converters.py
Expand Up @@ -38,7 +38,6 @@ def with_float_to_integer(sample, expect):
"""
)

@pytest.mark.flaky
def with_integer_to_float(sample, expect):
write(
'tmp/sample.yml',
Expand Down Expand Up @@ -73,7 +72,6 @@ def with_single_line(sample, expect):
"""
)

@pytest.mark.flaky
def with_multiple_lines(sample, expect):
sample.text = '\n'.join(f'Line {i+1}' for i in range(3))

Expand Down
1 change: 0 additions & 1 deletion tests/test_loading.py
Expand Up @@ -245,7 +245,6 @@ def with_extra_attributes(sample, expect):
expect(sample.nested.score) == 3.4
expect(hasattr(sample.nested, 'extra')).is_(False)

@pytest.mark.flaky
def with_multiple_levels(expect):
@dataclass
class Bottom:
Expand Down
5 changes: 0 additions & 5 deletions tests/test_patched_methods.py
Expand Up @@ -5,8 +5,6 @@
from dataclasses import dataclass, field
from typing import Dict, List

import pytest

from datafiles import datafile
from datafiles.utils import dedent, logbreak, read, write

Expand All @@ -32,7 +30,6 @@ class SampleWithNesting:


def describe_automatic_load():
@pytest.mark.flaky
def with_getattribute(expect):
sample = Sample()

Expand All @@ -48,7 +45,6 @@ def with_getattribute(expect):


def describe_automatic_save():
@pytest.mark.flaky
def with_setattr(expect):
sample = Sample()

Expand Down Expand Up @@ -186,7 +182,6 @@ def with_update(expect):


def describe_automatic_load_before_save():
@pytest.mark.flaky
def with_setattr(expect):
sample = Sample()

Expand Down

0 comments on commit 739645e

Please sign in to comment.