Skip to main content

file

Version: 9.2.3

wexample-file wraps local file and directory paths in typed Python objects — LocalFile and LocalDirectory — so each path is always stored as a resolved absolute pathlib.Path and carries a consistent set of operations: mtime-keyed read caching, write with automatic parent creation, touch, rename, and idempotent removal. It is aimed at Python 3.10+ projects that want predictable, typed filesystem access without raw pathlib calls scattered through application code.

Table of Contents

Installation

pip install wexample-file

Requires Python >=3.10.

Quickstart

Install the package:

pip install wexample-file

Working with a file

from wexample_file.common.local_file import LocalFile

f = LocalFile("/tmp/hello.txt")
f.write("hello, world")          # creates parent dirs automatically
content = f.read()               # "hello, world"
f.remove()                       # idempotent — no error if already gone

write creates any missing parent directories. read returns None when the file does not exist, and caches the content keyed on the file's mtime so repeated calls are cheap.

Working with a directory

from wexample_file.common.local_directory import LocalDirectory

d = LocalDirectory("/tmp/myapp/data")
d.create()    # mkdir -p equivalent
d.remove()    # shutil.rmtree, idempotent

Both classes accept a plain string or a pathlib.Path and always store a resolved absolute path in .path. Passing check_exists=True to either constructor raises FileNotFoundException or DirectoryNotFoundException when the path is absent.

Tests

This project uses pytest for testing and pytest-cov for code coverage analysis.

Installation

First, install the required testing dependencies:

.venv/bin/python -m pip install pytest pytest-cov

Basic Usage

Run all tests with coverage:

.venv/bin/python -m pytest --cov --cov-report=html

Common Commands

# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module

# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing

# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html

# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html

# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing

Viewing HTML Reports

After generating an HTML report, open htmlcov/index.html in your browser to view detailed line-by-line coverage information.

Coverage Threshold

To enforce a minimum coverage percentage:

.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80

This will cause the test suite to fail if coverage drops below 80%.

Architecture

The package (wexample-file, declared in pyproject.toml) lives entirely under src/wexample_file/ and splits into four namespaces: common, mixin, enum, and exception, plus a helper module for standalone utilities. There are no services, no I/O threads, and no global state — every call is synchronous and scoped to the instance it is made on.

common — the two concrete types

src/wexample_file/common/abstract_local_item_path.py defines AbstractLocalItemPath, which extends WithPathMixin from wexample_helpers. Its __init__ accepts a str or pathlib.Path, calls .expanduser().resolve(strict=False), and stores the result in self.path. That normalisation happens once at construction; all subsequent operations compare against the resolved path. The constructor also calls _validate_existing_type() before the optional check_exists guard, so a LocalFile pointing at an existing directory is always rejected, regardless of whether existence is being asserted.

The two concrete classes each implement the two abstract methods (item_type and remove) and add their own surface:

src/wexample_file/common/local_file.py — LocalFile

Holds _cached_content: str | None and _cached_mtime_ns: int | None. Every call to read() stats the file first; if the on-disk st_mtime_ns matches the cached value the content is returned without I/O. Any write or removal operation updates — or clears — both cache fields before returning, so the cache is always coherent with what the instance last wrote. read() returns None (not an exception) when the file is absent; check_exists=True at construction time is the opt-in for eager failure. _validate_existing_type() raises NotAFileException when the path exists but is a directory.

src/wexample_file/common/local_directory.py — LocalDirectory

Has no cache. create() calls mkdir(parents=True, exist_ok=True). remove() delegates to shutil.rmtree and is idempotent. _validate_existing_type() raises NotADirectoryException when the path exists but is not a directory.

mixin — composable entry points

src/wexample_file/mixin/with_local_file_mixin.py provides WithLocalFileMixin. Any class that also inherits WithPathMixin (and therefore has get_path()) gains get_local_file(), which constructs a LocalFile lazily and caches it on _local_file; if get_path() changes between calls the stale instance is discarded and a fresh one built.

src/wexample_file/mixin/with_local_directory_mixin.py provides WithLocalDirectoryMixin. get_local_directory() constructs a fresh LocalDirectory on every call — no per-instance cache, because LocalDirectory carries no mutable state.

enum — type discriminator

src/wexample_file/enum/local_path_type.py declares LocalPathType with two members, FILE and DIRECTORY. It is returned by item_type() on each concrete class and is available for any external code that needs to branch on kind without isinstance.

exception — typed errors

All four exceptions are decorated with @base_class from wexample_helpers and use its structured field/message protocol:

  • src/wexample_file/exception/file_not_found_exception.py — FileNotFoundException (error code FILE_NOT_FOUND), raised by LocalFile when check_exists=True and the path is absent.
  • src/wexample_file/exception/directory_not_found_exception.py — DirectoryNotFoundException (error code DIRECTORY_NOT_FOUND), raised by LocalDirectory under the same condition.
  • src/wexample_file/exception/not_a_file_exception.py — NotAFileException (error code FILE_EXPECTED), raised on construction when an existing path is a directory, and on write() for the same reason.
  • src/wexample_file/exception/not_a_directory_exception.py — NotADirectoryException (error code DIRECTORY_EXPECTED), raised on construction when an existing path is a regular file.

The not-found pair inherits LocalPathNotFoundException from wexample_helpers; the type-mismatch pair inherits UndefinedException.

helper — standalone utilities

src/wexample_file/helper/line.py exports line_count_recursive(path, pattern="*"), which walks a directory with rglob, opens each file with errors="ignore", and sums line counts. It operates on a plain pathlib.Path rather than the typed wrappers, so it can be used independently of the rest of the package.

Call path through a LocalFile.read()

  1. LocalFile("/some/path") — AbstractLocalItemPath.__init__ resolves the path, _validate_existing_type rejects it if it is a live directory.
  2. f.read() — is_file() returns False → None immediately; otherwise the method stats for st_mtime_ns.
  3. If mtime matches _cached_mtime_ns and _cached_content is set, the cached string is returned.
  4. Otherwise path.read_text(encoding=encoding) is called, followed by a second stat; both fields are updated before the method returns.

write() follows: mkdir for parents → write_text → stat → update _cached_content and _cached_mtime_ns. remove() calls unlink(missing_ok=True) and nulls both cache fields.

Tests

Tests live under tests/package/ and map directly to the source namespaces:

  • tests/package/common/test_local_file.py — covers instantiation with str/Path, extension parsing, read/write/remove/touch, cache coherence edge cases, and type-rejection.
  • tests/package/common/test_local_directory.py — covers instantiation, create, recursive remove, idempotency, and type-rejection.
  • tests/package/helper/test_line.py — covers empty directory, multi-file recursive count, and glob pattern filtering.

Integration in the Suite

This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.

The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.

Visit the Wexample Suite documentation for the complete package ecosystem.

Dependencies

  • attrs: >=23.1.0
  • cattrs: >=23.1.0
  • wexample-helpers: >=20.3.0

Versioning & Compatibility Policy

Wexample packages follow Semantic Versioning (SemVer):

  • MAJOR: Breaking changes
  • MINOR: New features, backward compatible
  • PATCH: Bug fixes, backward compatible

We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Free to use in both personal and commercial projects.

About us

Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.

This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.

Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.

Known Limitations & Roadmap

Current limitations and planned features are tracked in the GitHub issues.

See the project roadmap for upcoming features and improvements.

Status & Compatibility

Maturity: Production-ready

Python Support: >=3.10

OS Support: Linux, macOS, Windows

Status: Actively maintained

Migration Notes

When upgrading between major versions, refer to the migration guides in the documentation.

Breaking changes are clearly documented with upgrade paths and examples.

Metadata

Release files for wexample-file 9.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wexample-file 9.2.3
File Size Uploaded
wexample_file-9.2.3.tar.gz 21.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wexample-file 9.2.3
File Interpreter ABI Platform
wexample_file-9.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 41.6 kB

Release files / wexample_file-9.2.3.tar.gz

Download URL wexample_file-9.2.3.tar.gz
Size 21.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ec8299086ae38afa9f4565f3d1a1c218de1585019f03d226d1ae061a333cee9c
BLAKE2b-256 checksum
How to use checksums
91de7f85360493be77533c99c2356d8ac10cb128b11106cb12017a0260e260a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-142-generic

Release files / wexample_file-9.2.3-py3-none-any.whl

Download URL wexample_file-9.2.3-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
db0fd3c4104fafbfb594835e5625aeea2a7b15b7a862bafe517b17eb415115b5
BLAKE2b-256 checksum
How to use checksums
e48153ebb194fddafec6d58a25d07715a4d374741d62c2b4f68acd2fe9abee66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-142-generic

Release history Release notifications | RSS feed

This release

9.2.3 This release

2 release files

9.2.2

2 release files

9.2.1

2 release files

9.2.0

2 release files

9.1.6

2 release files

9.1.5

2 release files

9.1.4

2 release files

9.1.3

2 release files

9.1.2

2 release files

9.1.1

2 release files

9.1.0

2 release files

9.0.0

2 release files

8.2.0

2 release files

8.1.3

2 release files

8.1.2

2 release files

8.1.1

2 release files

8.1.0

2 release files

8.0.0

2 release files

6.6.3

2 release files

6.6.2

2 release files

6.6.1

2 release files

6.6.0

2 release files

6.5.1

2 release files

6.5.0

2 release files

6.4.0

2 release files

6.3.0

2 release files

6.0.28

2 release files

6.0.24

2 release files

6.0.23

2 release files

6.0.22

2 release files

6.0.21

2 release files

6.0.20

2 release files

0.0.63

2 release files

0.0.55

2 release files

0.0.54

2 release files

0.0.53

2 release files

0.0.49

2 release files

0.0.48

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page