synology_apm_repo.sdk.profiles.model module¶
Data model for saved S3/Azure/SMB connection profiles.
One canonical, UI-facing field-naming scheme (bucket/endpoint/
region/verify_tls/… rather than aws_access_key_id/
region_name/…) is used everywhere a profile’s fields are named — CLI
flags, the TUI’s saved/loaded field dicts, and the dataclasses here.
Translation to the third-party client’s own kwarg names is isolated to each
config dataclass’s client_kwargs property, never duplicated at each
call site.
Secret fields (S3’s access/secret key, Azure’s credential, SMB’s password)
never appear on these dataclasses — they live in the OS keyring (see
secrets.py) and are merged back in only by profiles.build_store.
- class synology_apm_repo.sdk.profiles.model.BackendKind(value)¶
Bases:
EnumWhich backend a profile targets.
- S3 = 's3'¶
- AZURE = 'azure'¶
- SMB = 'smb'¶
- class synology_apm_repo.sdk.profiles.model.S3ProfileConfig(bucket, endpoint=None, region=None, verify_tls=True)¶
Bases:
objectNon-secret
S3Storeconstructor inputs.access_key/secret_keyare not fields here — seesecrets.py.- property client_kwargs: dict[str, Any]¶
Everything but
bucketand the secret fields, already inS3Store/aioboto3’s own kwarg names. Callers merge the resolved secrets in on top of this dict.
- property display_fields: dict[str, str | None]¶
Ordered field-name -> value pairs for CLI/TUI display (a saved profile’s JSON and human-readable
showoutput alike) — the one place this backend’s own display field list is spelled out, so both renderers read it from here instead of each re-declaring it.
- class synology_apm_repo.sdk.profiles.model.AzureProfileConfig(container, account_url=None, verify_tls=True)¶
Bases:
objectNon-secret
AzureStoreconstructor inputs.credentialis not a field here — seesecrets.py.
- class synology_apm_repo.sdk.profiles.model.SmbProfileConfig(server, share, port=445, username=None)¶
Bases:
objectNon-secret
SmbStoreconstructor inputs.passwordis not a field here — seesecrets.py.usernametakes the Windows-nativeDOMAIN\username(oruser@domainUPN) form directly —smbprotocol’s own NTLM/SPNEGO layer splits the domain back out of that single string, so there is no separatedomainfield to keep in sync with it. Nopath/sub-root field either, matchingS3ProfileConfig/AzureProfileConfig: a share, like a bucket/container, is the whole scope one profile names.
- class synology_apm_repo.sdk.profiles.model.Profile(name, kind, config)¶
Bases:
objectOne saved profile, keyed by its user-chosen
name(unique across every backend kind). Never carries secret values.- kind: BackendKind¶
- config: S3ProfileConfig | AzureProfileConfig | SmbProfileConfig¶
- class synology_apm_repo.sdk.profiles.model.ProfileSummary(name, kind)¶
Bases:
objectCheap listing entry — derived from
profiles.jsonalone, no keyring access needed to produce it.- kind: BackendKind¶
- synology_apm_repo.sdk.profiles.model.S3_SECRET_FIELDS: tuple[str, ...] = ('access_key', 'secret_key')¶
Keyring “username” per secret field, and the
fieldsdict keyprofiles.load_profile/save_profileuse for it — seesecrets.pyfor how these map onto the underlying client’s own kwarg names.
- synology_apm_repo.sdk.profiles.model.secret_fields_for(kind)¶
Which
fieldsdict keys are secret (keyring-backed) forkind— the rest are plain config, persisted toprofiles.json.
- class synology_apm_repo.sdk.profiles.model.ProfileFieldSpec(name, strip=True, is_checkbox=False)¶
Bases:
objectOne profile field’s widget-binding shape, in canonical collection/ display order, for one backend — the single place a connection form (the TUI’s connect/saved-profile tabs today) reads a backend’s full field list from, instead of privately re-enumerating it.
stripisFalsefor a value whose leading/trailing whitespace might be significant (secret_key/credential/password) — not simply every secret field, sinceaccess_key(also keyring-backed, persecret_fields_for) has no such concern and is stripped like an ordinary field.
- synology_apm_repo.sdk.profiles.model.S3_FORM_FIELDS: tuple[ProfileFieldSpec, ...] = (ProfileFieldSpec(name='bucket', strip=True, is_checkbox=False), ProfileFieldSpec(name='endpoint', strip=True, is_checkbox=False), ProfileFieldSpec(name='region', strip=True, is_checkbox=False), ProfileFieldSpec(name='verify_tls', strip=True, is_checkbox=True), ProfileFieldSpec(name='access_key', strip=True, is_checkbox=False), ProfileFieldSpec(name='secret_key', strip=False, is_checkbox=False))¶
Each backend’s own field table — the CLI’s per-backend prompt collectors (
cli/commands/profile.py) keep their own field lists (each prompt has a distinct human label typer options don’t carry, so looping over this table there wouldn’t save anything); this is for a consumer that needs the field set/order and nothing else, one entry per real widget a connection form binds.
- synology_apm_repo.sdk.profiles.model.AZURE_FORM_FIELDS: tuple[ProfileFieldSpec, ...] = (ProfileFieldSpec(name='container', strip=True, is_checkbox=False), ProfileFieldSpec(name='account_url', strip=True, is_checkbox=False), ProfileFieldSpec(name='credential', strip=False, is_checkbox=False))¶
No
verify_tlsentry — unlike S3, no Azure connection form in this project has averify_tlswidget (AzureProfileConfig.verify_tlsonly ever takes its dataclass default here), so this table stays an explicit list rather than one derived fromAzureProfileConfig’s own dataclass fields.
- synology_apm_repo.sdk.profiles.model.form_fields_for(kind)¶
kind’s full field list, in canonical order — every field a connection form binds, secrets included, unlikedisplay_fields(non-secret only, read from an already-built config instance rather than named ahead of one existing).
- synology_apm_repo.sdk.profiles.model.client_kwargs_with_secrets(config, secrets)¶
config.client_kwargs, overlaid with whichever ofsecret_fields_for(kind)’s fieldssecretsactually carries a truthy value for — the shared shape behind every “resolve one profile’s config plus its secrets into constructor kwargs” call site (profiles.build_store,cli/commands/profile.py::_store_from_fields,browser/screens/connect_dialog.py’ss3_client_kwargs/azure_client_kwargs— SMB has no bucket-less/container-less “Browse” counterpart calling this directly, onlysmb_config_and_secretsfeedingstore_from_configstraight from_build_smb_store).secretsmay be a superset of what applies here (a not-yet-saved connection form carries every backend’s fields at once) — only the keyssecret_fields_fornames forconfig’s own kind are ever read from it; a present-but-falsy value (an empty string from an untouched form field) is treated the same as absent, matching every prior hand-rolled version of this check.