msw-plugin-api 0.2.3__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,5 +10,8 @@ build/
10
10
  .mypy_cache/
11
11
  .ruff_cache/
12
12
 
13
+ # library: do not commit the lockfile
14
+ uv.lock
15
+
13
16
  # hatch-vcs generated version file
14
17
  src/msw_plugin_api/_version.py
@@ -1,4 +1,4 @@
1
- Copyright (c) 2024-present Lars B. Rollik. All rights reserved.
1
+ Copyright (c) 2020-present Lars B. Rollik. All rights reserved.
2
2
 
3
3
  Permission is granted, free of charge, to use, copy, modify, and distribute
4
4
  this software and associated documentation files (the "Software") for
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: msw-plugin-api
3
- Version: 0.2.3
3
+ Version: 0.3.0
4
4
  Summary: Minimal structural interfaces for MSW plugin packages
5
5
  Project-URL: Homepage, https://github.com/MurineShiftWork/msw-plugin-api
6
6
  Project-URL: Issue Tracker, https://github.com/MurineShiftWork/msw-plugin-api/issues
7
7
  Author-email: "Lars B. Rollik" <lars@rollik.me>
8
- License: Copyright (c) 2024-present Lars B. Rollik. All rights reserved.
8
+ License: Copyright (c) 2020-present Lars B. Rollik. All rights reserved.
9
9
 
10
10
  Permission is granted, free of charge, to use, copy, modify, and distribute
11
11
  this software and associated documentation files (the "Software") for
@@ -44,7 +44,7 @@ Classifier: License :: Free for non-commercial use
44
44
  Classifier: Operating System :: OS Independent
45
45
  Classifier: Programming Language :: Python :: 3
46
46
  Classifier: Typing :: Typed
47
- Requires-Python: >=3.10
47
+ Requires-Python: >=3.11
48
48
  Provides-Extra: dev
49
49
  Requires-Dist: commitizen; extra == 'dev'
50
50
  Requires-Dist: mypy; extra == 'dev'
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -11,7 +11,7 @@ license = { file = "LICENSE" }
11
11
  authors = [
12
12
  { name = "Lars B. Rollik", email = "lars@rollik.me" },
13
13
  ]
14
- requires-python = ">=3.10"
14
+ requires-python = ">=3.11"
15
15
  dependencies = []
16
16
  classifiers = [
17
17
  "Development Status :: 4 - Beta",
@@ -52,7 +52,7 @@ dev = [
52
52
  [tool.commitizen]
53
53
  name = "cz_conventional_commits"
54
54
  version_provider = "commitizen"
55
- version = "0.2.3"
55
+ version = "0.3.0"
56
56
  version_files = ["VERSION"]
57
57
  tag_format = "v$version"
58
58
  update_changelog_on_bump = false
@@ -69,5 +69,5 @@ select = ["E", "W", "F", "I", "UP", "TCH", "PYI"]
69
69
  fixable = ["ALL"]
70
70
 
71
71
  [tool.mypy]
72
- python_version = "3.10"
72
+ python_version = "3.11"
73
73
  strict = true
@@ -0,0 +1,136 @@
1
+ """Minimal structural interfaces for MSW plugin packages.
2
+
3
+ Defines runtime-checkable Protocols and a concrete ``HostSessionInfo``
4
+ dataclass so plugins can implement the MSW host-session contract without
5
+ depending on the full murineshiftwork package.
6
+
7
+ Usage in a plugin::
8
+
9
+ from msw_plugin_api import HostSessionInfo, HostSessionProtocol
10
+
11
+ class MyHostSession:
12
+ def attach(self, **kwargs) -> HostSessionInfo: ...
13
+ def start(self) -> None: ...
14
+ def stop(self) -> None: ...
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from dataclasses import dataclass, field
20
+ from typing import Protocol, runtime_checkable
21
+
22
+
23
+ @dataclass
24
+ class HostSessionInfo:
25
+ """Data returned by a host session plugin after attaching.
26
+
27
+ ``session_name`` is the name of the host session directory (e.g. the Open
28
+ Ephys recording folder). MSW behavioural acquisitions are nested inside
29
+ it at ``parent_directory/subject/session_name/``.
30
+
31
+ Plugins may return this class directly or return any object whose
32
+ attributes satisfy ``HostSessionInfoProtocol``.
33
+
34
+ Args:
35
+ backend: Identifier for the recording backend (e.g. ``"open_ephys"``).
36
+ session_name: Name of the host session directory on disk.
37
+ subject: Subject identifier (e.g. animal ID).
38
+ parent_directory: Absolute path to the root recordings directory.
39
+ extra: Optional dict for backend-specific metadata.
40
+ """
41
+
42
+ backend: str
43
+ session_name: str
44
+ subject: str
45
+ parent_directory: str
46
+ extra: dict[str, object] = field(default_factory=dict)
47
+
48
+
49
+ @runtime_checkable
50
+ class HostSessionInfoProtocol(Protocol):
51
+ """Structural protocol for host session info objects.
52
+
53
+ Any object that exposes ``backend``, ``session_name``, ``subject``,
54
+ ``parent_directory``, and ``extra`` satisfies this protocol at runtime
55
+ via ``isinstance`` checks. ``HostSessionInfo`` implements it directly.
56
+ """
57
+
58
+ backend: str
59
+ session_name: str
60
+ subject: str
61
+ parent_directory: str
62
+ extra: dict[str, object]
63
+
64
+
65
+ @runtime_checkable
66
+ class HostSessionProtocol(Protocol):
67
+ """Structural protocol for MSW host session plugins.
68
+
69
+ Implement this interface structurally (no import of this package required)
70
+ and declare the entry point in ``pyproject.toml``::
71
+
72
+ [project.entry-points."msw.host"]
73
+ myplugin = "my_package.session:MyHostSession"
74
+
75
+ MSW core checks ``isinstance(session, HostSessionProtocol)`` at dispatch
76
+ time, so any class with ``attach``, ``start``, and ``stop`` will pass.
77
+ """
78
+
79
+ def attach(self, **kwargs: object) -> HostSessionInfoProtocol | None:
80
+ """Attach to the recording backend and return session info.
81
+
82
+ Args:
83
+ **kwargs: Backend-specific keyword arguments (e.g. port, host).
84
+
85
+ Returns:
86
+ A ``HostSessionInfoProtocol``-compatible object on success,
87
+ or ``None`` if the backend is unavailable.
88
+ """
89
+ ...
90
+
91
+ def start(self) -> None:
92
+ """Start the recording session on the backend."""
93
+ ...
94
+
95
+ def stop(self) -> None:
96
+ """Stop the recording session on the backend."""
97
+ ...
98
+
99
+
100
+ @runtime_checkable
101
+ class MetadataProtocol(Protocol):
102
+ """Structural protocol for an MSW metadata section.
103
+
104
+ A metadata addon owns exactly one top-level subtree of the manifest
105
+ ``metadata`` key-tree (e.g. ``metadata.probes``, ``metadata.opto``). It
106
+ keeps its schema in its own package and advertises itself with an entry
107
+ point::
108
+
109
+ [project.entry-points."msw.metadata"]
110
+ probes = "my_package.metadata:ProbesMetadata"
111
+
112
+ MSW core discovers these via ``importlib.metadata`` and checks
113
+ ``isinstance(obj, MetadataProtocol)``, so any object exposing ``subtree``,
114
+ ``schema_version``, and ``validate`` satisfies it (no import of this
115
+ package required). ``validate`` must be non-fatal: it returns a list of
116
+ human-readable warnings and never raises, because ``metadata`` is optional
117
+ and legacy/partial trees must still load.
118
+
119
+ Attributes:
120
+ subtree: The reserved top-level metadata key this addon owns.
121
+ schema_version: The version of this subtree's schema.
122
+ """
123
+
124
+ subtree: str
125
+ schema_version: int
126
+
127
+ def validate(self, block: object) -> list[str]:
128
+ """Validate this addon's metadata subtree.
129
+
130
+ Args:
131
+ block: The value at ``metadata[self.subtree]``.
132
+
133
+ Returns:
134
+ A list of human-readable warnings (empty when valid). Never raises.
135
+ """
136
+ ...
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.3'
22
- __version_tuple__ = version_tuple = (0, 2, 3)
21
+ __version__ = version = '0.3.0'
22
+ __version_tuple__ = version_tuple = (0, 3, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1 +0,0 @@
1
- 0.2.3
@@ -1,65 +0,0 @@
1
- """Minimal structural interfaces for MSW plugin packages.
2
-
3
- Defines runtime-checkable Protocols and a concrete HostSessionInfo dataclass
4
- so plugins can implement the MSW host-session contract without depending on
5
- the full murineshiftwork package.
6
-
7
- Usage in a plugin::
8
-
9
- from msw_plugin_api import HostSessionInfo, HostSessionProtocol
10
-
11
- class MyHostSession:
12
- def attach(self, **kwargs) -> HostSessionInfo: ...
13
- def start(self) -> None: ...
14
- def stop(self) -> None: ...
15
- """
16
-
17
- from __future__ import annotations
18
-
19
- from dataclasses import dataclass, field
20
- from typing import Protocol, runtime_checkable
21
-
22
-
23
- @dataclass
24
- class HostSessionInfo:
25
- """Data returned by a host session plugin after attaching.
26
-
27
- ``session_name`` is the name of the host session directory (e.g. the Open
28
- Ephys recording folder). MSW behavioural acquisitions are nested inside
29
- it: ``basepath/subject/session_name/acquisition_basename/``.
30
-
31
- Plugins may return this class directly or return any object whose
32
- attributes satisfy HostSessionInfoProtocol.
33
- """
34
-
35
- backend: str
36
- session_name: str
37
- subject: str
38
- parent_directory: str
39
- extra: dict[str, object] = field(default_factory=dict)
40
-
41
-
42
- @runtime_checkable
43
- class HostSessionInfoProtocol(Protocol):
44
- """Structural protocol for host session info objects."""
45
-
46
- backend: str
47
- session_name: str
48
- subject: str
49
- parent_directory: str
50
- extra: dict[str, object]
51
-
52
-
53
- @runtime_checkable
54
- class HostSessionProtocol(Protocol):
55
- """Structural protocol for MSW host session plugins.
56
-
57
- Implement this interface (structurally — no import required) and declare::
58
-
59
- [project.entry-points."msw.host"]
60
- myplugin = "my_package.session:MyHostSession"
61
- """
62
-
63
- def attach(self, **kwargs: object) -> HostSessionInfoProtocol | None: ...
64
- def start(self) -> None: ...
65
- def stop(self) -> None: ...
File without changes