DSM Processing¶
This chapter covers loading and processing DSM (Digital Substrate Model) files in Python.
The DSM Workflow¶
Processing DSM files follows three steps:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ assemble │ ──► │ parse │ ──► │ introspect │
│ (.dsm) │ │ (validate) │ │ (visit) │
└─────────────┘ └─────────────┘ └─────────────┘
Step 1: Assemble¶
DSMBuilder.assemble() reads DSM files:
>>> from dsviper import *
# Assemble a single file
>>> builder = DSMBuilder.assemble("model.dsm")
# Assemble all .dsm files in a directory
>>> builder = DSMBuilder.assemble("models")
# View assembled parts
>>> for part in builder.parts():
... print(part.source())
If the path is a directory, all .dsm files are assembled together and parsed as a single
unit.
Step 2: Parse¶
parse() validates syntax and semantics, returning three values:
>>> report, dsm_defs, defs = builder.parse()
Return Value |
Type |
Description |
|---|---|---|
|
|
Errors and warnings |
|
|
Structured DSM data (or None if errors) |
|
|
Runtime definitions (or None if errors) |
Handling Errors¶
>>> report, dsm_defs, defs = builder.parse()
>>> if report.has_errors():
...
for error in report.errors():
...
print(f"{error.source()}:{error.line()}: {error.message()}")
... else:
...
print("Parse successful!")
Step 3: DSM Introspection¶
DSMDefinitions provides structured access to inspect the parsed model.
DSMDefinitions¶
The root container for all DSM elements:
>>> dsm_defs.concepts()
[Tuto::User]
>>> dsm_defs.structures()
[Tuto::Login, Tuto::Identity]
>>> dsm_defs.enumerations()
[Tuto::Status]
>>> dsm_defs.attachments()
[attachment<User, Login> Tuto::login, attachment<User, Identity> Tuto::identity]
DSMConcept¶
Inspect concept definitions:
>>> concept = dsm_defs.concepts()[0]
>>> concept.type_name()
Tuto::User
>>> concept.runtime_id()
'a1b2c3d4-...'
>>> concept.documentation()
'A user in the system.'
>>> concept.parent() # None if no parent
Tuto::Admin
DSMStructure¶
Inspect structure definitions and their fields:
>>> struct = dsm_defs.structures()[0]
>>> struct.type_name()
Tuto::Login
>>> for field in struct.fields():
...
print(f"{field.name()}: {field.type()}")
nickname: string
password: string
>>> field = struct.fields()[0]
>>> field.documentation()
'The user display name.'
>>> field.default_value()
''
DSMAttachment¶
Inspect attachment definitions:
>>> att = dsm_defs.attachments()[0]
>>> att.identifier()
'login'
>>> att.key_type()
Tuto::User
>>> att.document_type()
Tuto::Login
Generate DSM Text¶
Reconstruct DSM source from definitions:
>>> print(dsm_defs.to_dsm())
namespace Tuto {f529bc42 - ...} {
concept User;
struct Login {
string nickname;
string password;
};
attachment<User, Login> login;
};
Using Runtime Definitions¶
The DefinitionsConst from parse enables runtime operations:
Inject Constants¶
>>> defs.inject()
# Constants are now available
>>> TUTO_S_LOGIN
Tuto::Login
>>> TUTO_A_USER_LOGIN
attachment<User, Login> Tuto::login
Naming convention: Constants follow the pattern {NAMESPACE}_{KIND}_{NAME}:
Kind |
Prefix |
Example |
Description |
|---|---|---|---|
Attachment |
|
|
Attachment type |
Structure |
|
|
Structure type |
Enumeration |
|
|
Enumeration type |
Concept |
|
|
Concept type |
Path |
|
|
Path to field |
Query Types¶
>>> types = defs.query_types("Login")
>>> t_login = types[0]
>>> Value.create(t_login)
{nickname = '', password = ''}
Access Attachments¶
>>> for att in defs.attachments():
...
print(att.description())
Serialization¶
DSMDefinitions can be serialized for distribution:
Binary (DSMB)¶
# Encode
>>> blob = dsm_defs.encode()
# Decode
>>> dsm_defs = DSMDefinitions.decode(blob)
JSON¶
# Encode
>>> json_str = dsm_defs.json_encode()
# Decode
>>> dsm_defs = DSMDefinitions.json_decode(json_str)
What’s Next¶
Tutorial - Complete workflow using DSM with CommitDatabase
Database - Persistence with Database and CommitDatabase
Serialization - Binary and JSON encoding