punchboot 2.0.0__tar.gz → 2.2.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.
Files changed (35) hide show
  1. {punchboot-2.0.0 → punchboot-2.2.0}/PKG-INFO +1 -1
  2. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/PKG-INFO +1 -1
  3. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/__init__.py +2 -0
  4. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/helpers.py +2 -1
  5. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/session.py +29 -10
  6. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/python_wrapper.c +34 -10
  7. {punchboot-2.0.0 → punchboot-2.2.0}/LICENSE +0 -0
  8. {punchboot-2.0.0 → punchboot-2.2.0}/README.md +0 -0
  9. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/SOURCES.txt +0 -0
  10. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/dependency_links.txt +0 -0
  11. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/entry_points.txt +0 -0
  12. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/requires.txt +0 -0
  13. {punchboot-2.0.0 → punchboot-2.2.0}/punchboot.egg-info/top_level.txt +0 -0
  14. {punchboot-2.0.0 → punchboot-2.2.0}/pyproject.toml +0 -0
  15. {punchboot-2.0.0 → punchboot-2.2.0}/setup.cfg +0 -0
  16. {punchboot-2.0.0 → punchboot-2.2.0}/setup.py +0 -0
  17. {punchboot-2.0.0 → punchboot-2.2.0}/src/lib/bpak.c +0 -0
  18. {punchboot-2.0.0 → punchboot-2.2.0}/src/wire.c +0 -0
  19. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api.c +0 -0
  20. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_authentication.c +0 -0
  21. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_board.c +0 -0
  22. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_boot.c +0 -0
  23. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_device.c +0 -0
  24. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_misc.c +0 -0
  25. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_partition.c +0 -0
  26. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_slc.c +0 -0
  27. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/api_stream.c +0 -0
  28. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/error.c +0 -0
  29. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/exceptions.c +0 -0
  30. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/__main__.py +0 -0
  31. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/partition.py +0 -0
  32. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/py.typed +0 -0
  33. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/punchboot/slc.py +0 -0
  34. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/socket.c +0 -0
  35. {punchboot-2.0.0 → punchboot-2.2.0}/tools/punchboot/usb.c +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: punchboot
3
- Version: 2.0.0
3
+ Version: 2.2.0
4
4
  Summary: Punchboot tools
5
5
  Home-page: https://github.com/jonasblixt/punchboot
6
6
  Author: Jonas Blixt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: punchboot
3
- Version: 2.0.0
3
+ Version: 2.2.0
4
4
  Summary: Punchboot tools
5
5
  Home-page: https://github.com/jonasblixt/punchboot
6
6
  Author: Jonas Blixt
@@ -4,6 +4,7 @@ from _punchboot import ( # type: ignore # noqa: F401
4
4
  ArgumentError,
5
5
  AuthenticationError,
6
6
  CommandError,
7
+ Error,
7
8
  GenericError,
8
9
  IOError,
9
10
  KeyRevokedError,
@@ -26,6 +27,7 @@ from .session import Session
26
27
  from .slc import SLC
27
28
 
28
29
  _pb_exceptions = [
30
+ "Error",
29
31
  "GenericError",
30
32
  "AuthenticationError",
31
33
  "NotAuthenticatedError",
@@ -1,6 +1,7 @@
1
1
  """Various punchboot helper functions."""
2
2
 
3
3
  import uuid
4
+ from importlib.metadata import version
4
5
  from typing import Iterable
5
6
 
6
7
  import _punchboot # type: ignore
@@ -9,7 +10,7 @@ import semver
9
10
 
10
11
  def library_version() -> semver.Version:
11
12
  """Return the version string of the C library."""
12
- return semver.VersionInfo.parse(_punchboot.version())
13
+ return semver.Version.parse(version('punchboot'))
13
14
 
14
15
 
15
16
  def pb_id(cmd: str) -> int:
@@ -7,7 +7,7 @@ import hashlib
7
7
  import io
8
8
  import pathlib
9
9
  import uuid
10
- from typing import Any, Callable, Iterable, Optional, Tuple, Union
10
+ from typing import IO, Any, Callable, Iterable, Optional, Tuple, Union
11
11
 
12
12
  import _punchboot # type: ignore
13
13
  import semver
@@ -17,6 +17,18 @@ from .partition import Partition, PartitionFlags
17
17
  from .slc import SLC
18
18
 
19
19
 
20
+ def _has_fileno(file: IO[bytes]) -> bool:
21
+ if not hasattr(file, "fileno"):
22
+ return False
23
+
24
+ try:
25
+ file.fileno()
26
+ except io.UnsupportedOperation:
27
+ return False
28
+
29
+ return True
30
+
31
+
20
32
  class Session(object):
21
33
  """Punchboot session class.
22
34
 
@@ -45,6 +57,13 @@ class Session(object):
45
57
  )
46
58
  self._s = _punchboot.Session(_device_uuid, _socket_path)
47
59
 
60
+ def close(self):
61
+ """Close the current session.
62
+
63
+ This will invalidate the session object.
64
+ """
65
+ self._s.close()
66
+
48
67
  def authenticate(self, password: str):
49
68
  """Authenticate session using a password.
50
69
 
@@ -101,7 +120,7 @@ class Session(object):
101
120
  ]
102
121
 
103
122
  def part_verify(
104
- self, file: Union[pathlib.Path, io.BufferedReader, bytes], part: Union[uuid.UUID, str]
123
+ self, file: Union[pathlib.Path, IO[bytes], bytes], part: Union[uuid.UUID, str]
105
124
  ):
106
125
  """Verify the contents of a partition.
107
126
 
@@ -123,7 +142,7 @@ class Session(object):
123
142
  _bpak_header_valid: bool = False
124
143
  _hash_ctx = hashlib.sha256()
125
144
 
126
- def _chunk_reader(fh: io.BufferedReader) -> int:
145
+ def _chunk_reader(fh: IO[bytes]) -> int:
127
146
  _length: int = 0
128
147
  nonlocal _bpak_header_valid
129
148
  # Check if the first 4k contains a valid BPAK header
@@ -141,18 +160,18 @@ class Session(object):
141
160
  if isinstance(file, pathlib.Path):
142
161
  with file.open("rb") as f:
143
162
  _data_length = _chunk_reader(f)
144
- elif isinstance(file, io.BufferedReader):
145
- _data_length = _chunk_reader(file)
146
163
  elif isinstance(file, bytes):
147
164
  _hash_ctx.update(file)
148
165
  _bpak_header_valid = valid_bpak_magic(file)
149
166
  _data_length = len(file)
167
+ elif _has_fileno(file):
168
+ _data_length = _chunk_reader(file)
150
169
  else:
151
170
  raise ValueError("Unacceptable input")
152
171
 
153
172
  self._s.part_verify(_uu.bytes, _hash_ctx.digest(), _data_length, _bpak_header_valid)
154
173
 
155
- def part_write(self, file: Union[pathlib.Path, io.BufferedReader], part: Union[uuid.UUID, str]):
174
+ def part_write(self, file: Union[pathlib.Path, IO[bytes]], part: Union[uuid.UUID, str]):
156
175
  """Write data to a partition.
157
176
 
158
177
  Keyword arguments:
@@ -163,12 +182,12 @@ class Session(object):
163
182
  if isinstance(file, pathlib.Path):
164
183
  with file.open("rb") as f:
165
184
  self._s.part_write(f, _uu.bytes)
166
- elif isinstance(file, io.BufferedReader):
185
+ elif _has_fileno(file):
167
186
  self._s.part_write(file, _uu.bytes)
168
187
  else:
169
188
  raise ValueError("Unacceptable input")
170
189
 
171
- def part_read(self, file: Union[pathlib.Path, io.BufferedReader], part: Union[uuid.UUID, str]):
190
+ def part_read(self, file: Union[pathlib.Path, IO[bytes]], part: Union[uuid.UUID, str]):
172
191
  """Read data from a partition to a file.
173
192
 
174
193
  Keyword arguments:
@@ -179,7 +198,7 @@ class Session(object):
179
198
  if isinstance(file, pathlib.Path):
180
199
  with file.open("wb") as f:
181
200
  self._s.part_read(f, _uu.bytes)
182
- elif isinstance(file, io.BufferedReader):
201
+ elif _has_fileno(file):
183
202
  self._s.part_read(file, _uu.bytes)
184
203
  else:
185
204
  raise ValueError("Unacceptable input")
@@ -330,7 +349,7 @@ class Session(object):
330
349
  _ver_str: str = self._s.device_get_punchboot_version()
331
350
  if _ver_str.startswith("v"):
332
351
  _ver_str = _ver_str[1:]
333
- return semver.VersionInfo.parse(_ver_str)
352
+ return semver.Version.parse(_ver_str)
334
353
 
335
354
  def device_get_uuid(self) -> uuid.UUID:
336
355
  """Read the device UUID."""
@@ -24,17 +24,25 @@
24
24
 
25
25
  static int log_cb(struct pb_context *ctx, int level, const char *fmt, ...)
26
26
  {
27
- static PyObject *logging = NULL;
27
+ static PyObject *logger = NULL;
28
28
  static PyObject *log_msg = NULL;
29
29
  char msg_buf[1024];
30
30
  int rc;
31
31
  (void)ctx;
32
32
  (void)level;
33
33
 
34
- if (logging == NULL) {
35
- logging = PyImport_ImportModuleNoBlock("logging");
34
+ if (logger == NULL) {
35
+ PyObject *logging = PyImport_ImportModuleNoBlock("logging");
36
36
  if (logging == NULL) {
37
37
  PyErr_SetString(PyExc_ImportError, "Could not import module 'logging'");
38
+ return -1;
39
+ }
40
+
41
+ logger = PyObject_CallMethod(logging, "getLogger", "s", "pb");
42
+
43
+ if (logger == NULL) {
44
+ PyErr_SetString(PyExc_RuntimeError, "Can't configure logger");
45
+ return -1;
38
46
  }
39
47
  }
40
48
 
@@ -48,7 +56,7 @@ static int log_cb(struct pb_context *ctx, int level, const char *fmt, ...)
48
56
  msg_buf[rc - 1] = 0;
49
57
 
50
58
  log_msg = Py_BuildValue("s", msg_buf);
51
- PyObject_CallMethod(logging, "debug", "O", log_msg);
59
+ PyObject_CallMethod(logger, "debug", "O", log_msg);
52
60
  Py_DECREF(log_msg);
53
61
  }
54
62
  va_end(args);
@@ -124,14 +132,27 @@ static int PbSession_init(struct pb_session *self, PyObject *args, PyObject *kwd
124
132
  return 0;
125
133
  }
126
134
 
127
- static void PbSession_dealloc(struct pb_session *self)
135
+ static void close_pb_session(struct pb_session *self)
128
136
  {
129
137
  if (self->ctx) {
130
138
  pb_api_free_context(self->ctx);
131
139
  }
140
+ self->ctx = NULL;
141
+ }
142
+
143
+ static void PbSession_dealloc(struct pb_session *self)
144
+ {
145
+ close_pb_session(self);
132
146
  Py_TYPE(self)->tp_free((PyObject *)self);
133
147
  }
134
148
 
149
+ static PyObject *session_close(PyObject *self, PyObject *Py_UNUSED(args))
150
+ {
151
+ struct pb_session *session = (struct pb_session *)self;
152
+ close_pb_session(session);
153
+ Py_RETURN_NONE;
154
+ }
155
+
135
156
  static PyObject *authenticate(PyObject *self, PyObject *args, PyObject *kwds)
136
157
  {
137
158
  struct pb_session *session = (struct pb_session *)self;
@@ -849,6 +870,10 @@ static PyObject *board_run_command(PyObject *self, PyObject *args, PyObject *kwd
849
870
  }
850
871
 
851
872
  static PyMethodDef PbSession_methods[] = {
873
+ { "close",
874
+ session_close,
875
+ METH_NOARGS,
876
+ "Close the current session (invalidates the session object)" },
852
877
  /* Password API */
853
878
  {
854
879
  "authenticate",
@@ -1042,13 +1067,12 @@ static PyObject *wait_for_device(PyObject *self, PyObject *args, PyObject *kwds)
1042
1067
 
1043
1068
  while (true) {
1044
1069
  rc = init_transport(NULL, NULL, &ctx);
1045
- if (rc != PB_RESULT_OK) {
1046
- PyErr_SetString(PyExc_TimeoutError, "No device found");
1047
- return NULL;
1070
+
1071
+ if (rc == PB_RESULT_OK) {
1072
+ rc = get_uuid(ctx, uuid);
1073
+ pb_api_free_context(ctx);
1048
1074
  }
1049
1075
 
1050
- rc = get_uuid(ctx, uuid);
1051
- pb_api_free_context(ctx);
1052
1076
  if (rc != PB_RESULT_OK) {
1053
1077
  if (timeout > 0) {
1054
1078
  sleep(1);
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes