修改为东南天坐标系
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
"""Domain-model objects.
|
||||
|
||||
This module should have no dependencies outside the domain model. In particular, any domain model
|
||||
object should be importable anywhere in the package without risk of producing an import cycle.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime as dt
|
||||
import uuid
|
||||
from typing import Iterator, Protocol
|
||||
|
||||
from oxmsg.util import lazyproperty
|
||||
|
||||
# ================================================================================================
|
||||
# EXCEPTIONS
|
||||
# ================================================================================================
|
||||
|
||||
|
||||
class UnrecognizedCodePageError(Exception):
|
||||
"""The specified code-page is not a known Microsoft encoding."""
|
||||
|
||||
|
||||
class UnsupportedEncodingError(Exception):
|
||||
"""The encoding used for this MSG object has no built-in Python codec."""
|
||||
|
||||
|
||||
# ================================================================================================
|
||||
# INTERFACES
|
||||
# ================================================================================================
|
||||
|
||||
|
||||
class PropStorageT(Protocol):
|
||||
"""The interface required of a storage object to extract the properties of that storage."""
|
||||
|
||||
@lazyproperty
|
||||
def properties_stream_bytes(self) -> bytes:
|
||||
"""Bytes of stream containing properties for the top-level object this storage represents.
|
||||
|
||||
Every storage must have exactly one such stream.
|
||||
"""
|
||||
...
|
||||
|
||||
def property_stream_bytes(self, pid: int, ptyp: int) -> bytes:
|
||||
"""The bytes of the stream for variable-length property identified by `pid`."""
|
||||
...
|
||||
|
||||
|
||||
class PropertyT(Protocol):
|
||||
"""The interface required of a property object, regardless of its type."""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""The Microsft name for this property, like "PidTagMessageClass"."""
|
||||
...
|
||||
|
||||
@property
|
||||
def pid(self) -> int:
|
||||
"""The property-id (PID) for this property, like 0x3701 for attachment bytes."""
|
||||
...
|
||||
|
||||
@property
|
||||
def ptyp(self) -> int:
|
||||
"""The property-type (PTYP) for this property, like 0x0102 for PtypBinary."""
|
||||
...
|
||||
|
||||
@property
|
||||
def ptyp_name(self) -> str:
|
||||
"""The Microsft name for the type of this property, like "PtypString"."""
|
||||
...
|
||||
|
||||
@lazyproperty
|
||||
def value(self) -> bool | bytes | dt.datetime | float | int | str | uuid.UUID:
|
||||
"""The value of this property, its type depending on the property."""
|
||||
...
|
||||
|
||||
|
||||
class StorageT(Protocol):
|
||||
"""Interface for a storage object."""
|
||||
|
||||
def iter_attachment_storages(self) -> Iterator[StorageT]:
|
||||
"""Generate each storage object specific to an attachment to this message."""
|
||||
...
|
||||
|
||||
def iter_recipient_storages(self) -> Iterator[StorageT]:
|
||||
"""Generate each storage object specific to a recipient of this message."""
|
||||
...
|
||||
|
||||
@lazyproperty
|
||||
def name(self) -> str:
|
||||
"""The last segment of the storage path.
|
||||
|
||||
This is the empty string for the root storage. Other storages are named is clearly specified
|
||||
ways depending on the type of top-level object they contain, e.g. attachment, recipient,
|
||||
etc.
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def path(self) -> str:
|
||||
"""String identifier for this storage; its location within the OXMSG CFB.
|
||||
|
||||
- Suitable as a unique storage identifier within the MSG file.
|
||||
- The path of the root storage is the empty string ("").
|
||||
"""
|
||||
...
|
||||
|
||||
@lazyproperty
|
||||
def properties_stream_bytes(self) -> bytes:
|
||||
"""Bytes of stream containing properties for the top-level object this storage represents.
|
||||
|
||||
Every storage must have exactly one such stream.
|
||||
"""
|
||||
...
|
||||
|
||||
def property_stream_bytes(self, pid: int, ptyp: int) -> bytes:
|
||||
"""The bytes of the stream for variable-length property identified by `pid`."""
|
||||
...
|
||||
|
||||
|
||||
class StreamT(Protocol):
|
||||
"""Interface for a stream object."""
|
||||
|
||||
@lazyproperty
|
||||
def name(self) -> str:
|
||||
"""The last segment of the stream path.
|
||||
|
||||
Each stream contains the bytes for a property. The form of a stream name is clearly
|
||||
specified in the OXMSG standard and includes both the property-id (PID) and property
|
||||
data-type (PTYP) for the property data it contains.
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def path(self) -> str:
|
||||
"""String identifier for this storage; its location within the OXMSG CFB.
|
||||
|
||||
Suitable as a unique storage identifier within the MSG file.
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def bytes_(self) -> bytes:
|
||||
"""The bytes contained in this stream."""
|
||||
...
|
||||
|
||||
|
||||
# ================================================================================================
|
||||
# MASKS
|
||||
# ================================================================================================
|
||||
|
||||
# -- AF = attachment flag maybe? Means attachment is embedding, i.e. referenced "by value" --
|
||||
AF_BY_VALUE = 0x00000001
|
||||
|
||||
STORE_UNICODE_OK = 0x00040000
|
||||
|
||||
|
||||
# ================================================================================================
|
||||
# PROPERTY STREAM HEADER OFFSETS
|
||||
# ================================================================================================
|
||||
|
||||
# -- The starting location for the 16-byte property segments within the property stream varies
|
||||
# -- depending on the storage type.
|
||||
|
||||
ATTACH_HDR_OFFSET = 8
|
||||
MSG_HDR_OFFSET = 32
|
||||
RECIP_HDR_OFFSET = 8
|
||||
Reference in New Issue
Block a user