Skip to main content

dotproperties

A zero-dependency, pure-Python reader and writer for Java Properties.

CI Codecov PyPI Python 3.10–3.14 Free-threaded CPython 3.14t License: MIT

dotproperties reads and writes the classic line-oriented java.util.Properties format.

It handles comments, continuations, separators, duplicate keys, Java escapes, and UTF-16 surrogate pairs. Byte and text input follow Java's distinct InputStream and Reader rules, and interoperability is checked against all current Eclipse Temurin LTS lines: 8, 11, 17, 21, and 25.

Install

Add dotproperties to a uv-managed project:

uv add dotproperties

Or install it with pip:

pip install dotproperties

Python 3.10 through 3.14 and free-threaded CPython 3.14t are supported. Python 3.15 and 3.15t previews are tested for forward compatibility until Python 3.15 is released.

Quick start

Parse a string with loads():

import dotproperties

config = dotproperties.loads(
    """
    # Application settings
    host = localhost
    port: 8080
    greeting = Olá
    """
)

print(config)
{'host': 'localhost', 'port': '8080', 'greeting': 'Olá'}

Serialize a mapping with dumps():

text = dotproperties.dumps(config)
print(text, end="")
host=localhost
port=8080
greeting=Ol\u00E1

Read and write files with load() and dump():

with open("application.properties", "rb") as fp:
    config = dotproperties.load(fp)

with open("application.properties", "w", encoding="ascii") as fp:
    dotproperties.dump(config, fp)

Encoding and streams

Strings and text streams are already-decoded character input, corresponding to Java's Properties.load(Reader). Bytes and binary streams use ISO-8859-1, matching Properties.load(InputStream).

Serialization produces text and escapes every non-ASCII code point by default, so the result is safe to write as ASCII and load through either Java path. Keys and values must be strings.

Set ensure_ascii=False to retain readable Unicode:

text = dotproperties.dumps({"greeting": "你好"}, ensure_ascii=False)

with open("application.properties", "w", encoding="utf-8") as fp:
    fp.write(text)

Load that file through a Java Reader using the same encoding. Passing its UTF-8 bytes to Properties.load(InputStream) would apply ISO-8859-1 instead.

Serialization options

Use sort_keys=True for deterministic output in Java's UTF-16 string order, including the ordering difference between supplementary and BMP characters. The default preserves the mapping's iteration order.

Add caller-controlled header comments with comments:

text = dotproperties.dumps(
    config,
    sort_keys=True,
    comments="Application settings",
)

Multiline comments follow Java's # and ! line-marker rules. CR, LF, and CRLF are normalized to LF, and ensure_ascii applies to comment text as well as keys and values.

load() makes bounded-size read requests. load() and dump() leave caller-owned streams open; dump() also leaves flushing to the caller and validates the complete mapping before its first write. A malformed \uXXXX escape raises ValueError.

dotproperties.__version__ reports the installed package version.

Format behavior

  • Leading spaces, tabs, and form feeds are ignored. # and ! begin comment lines after that leading whitespace; comment lines cannot be continued.
  • An odd run of trailing backslashes continues a logical line. Leading format whitespace on the next natural line is discarded.
  • The first unescaped =, :, space, tab, or form feed separates the key from the value. A missing value is the empty string.
  • \t, \n, \r, \f, and \uXXXX use Java's meanings. For other escaped characters, Java's rule drops the backslash.
  • Valid UTF-16 surrogate pairs become one Python Unicode character. Isolated surrogate units remain isolated and are always serialized as escapes.
  • Duplicate keys use the last value, matching Properties.load().

Parsing does not preserve comments or original spelling. Serialization emits optional caller-supplied comments followed by key=value lines; it does not add Java's timestamp comment. Entries follow the mapping's iteration order unless sort_keys=True. Java 8 does not specify the order used by Properties.store(), while Java 25 sorts ordinary Properties by key.

Safety and resource limits

The line format is data-only. Parsing does not construct Python objects from type tags, evaluate expressions, expand variables, follow includes, or access external resources.

Like Properties.load(), dotproperties does not impose a document-size, logical-line, or entry-count limit. Bounded-size requests to fp.read() do not cap total CPU or memory use; the result and the longest unfinished logical line must still fit in memory. Applications accepting untrusted input should limit it before parsing.

dump() prevents invalid mapping entries from causing partial output, but an I/O failure can still interrupt a write. Applications that replace important files should write to a temporary file and perform an atomic replacement.

Development

The default development interpreter is Python 3.12. See CONTRIBUTING.md for setup, checks, interoperability testing, and releases. Report suspected vulnerabilities through the security policy. Participation is governed by the code of conduct.

License

dotproperties is available under the MIT License.

Metadata

Release files for dotproperties 0.2.0

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

Source distribution (sdist)

Source distribution for dotproperties 0.2.0
File Size Uploaded
dotproperties-0.2.0.tar.gz 47.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dotproperties 0.2.0
File Interpreter ABI Platform
dotproperties-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 57.6 kB

Release files / dotproperties-0.2.0.tar.gz

Download URL dotproperties-0.2.0.tar.gz
Size 47.5 kB
Tags Source
SHA-256 checksum
How to use checksums
36b453f3a2460bb18ff7260bbd839fbdecb1f5aaac9fa4c82787846a976ab1cd
BLAKE2b-256 checksum
How to use checksums
6fbeb823198ccae26ada927f1788de19feaec542823a2fdbb4f40469dc14fa9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release files / dotproperties-0.2.0-py3-none-any.whl

Download URL dotproperties-0.2.0-py3-none-any.whl
Size 10.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
52d8ed9e75624146ac53b839e52f53133077600aaf8ca9c52164fb22dee79881
BLAKE2b-256 checksum
How to use checksums
62081ccf98b398e7cdc710de1a3999df70261328bbe0b5c412ce11fde9b01c48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

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