Skip to main content

file

Version: 9.2.2

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.2.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.2

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.2
File Size Uploaded
wexample_file-9.2.2.tar.gz 21.2 kB Details

Built distribution (wheel)

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

Total release size: 41.6 kB

Release files / wexample_file-9.2.2.tar.gz

Download URL wexample_file-9.2.2.tar.gz
Size 21.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c65f36f8625ec827f2e330bb851984387010917eafdcd46203066115e3df4995
BLAKE2b-256 checksum
How to use checksums
4be43c91081e08416ad5057397c5b3e1f3c8bb857381b4b11be601545e2316c4
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-139-generic

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

Download URL wexample_file-9.2.2-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80c41106a3617873c3c3f7fe840058f3bc238207af04ea67f4013d8cbc2de094
BLAKE2b-256 checksum
How to use checksums
b32771ccbe12528becdb1637bce6216dc51ae668520eb43728afcc977dcf66e7
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-139-generic

Release history Release notifications | RSS feed

9.2.3

2 release files

This release

9.2.2 This release

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