goosebit 0.2.9__py3-none-any.whl → 0.2.10__py3-none-any.whl

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.
@@ -5,7 +5,7 @@ from datetime import datetime
5
5
  from enum import Enum, IntEnum, StrEnum
6
6
  from typing import Annotated
7
7
 
8
- from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, computed_field
8
+ from pydantic import BaseModel, BeforeValidator, ConfigDict, computed_field
9
9
 
10
10
  from goosebit.db.models import UpdateModeEnum, UpdateStateEnum
11
11
  from goosebit.schema.software import HardwareSchema, SoftwareSchema
@@ -34,8 +34,8 @@ class DeviceSchema(BaseModel):
34
34
  name: str | None
35
35
  sw_version: str | None
36
36
 
37
- assigned_software: SoftwareSchema | None = Field(exclude=True)
38
- hardware: HardwareSchema | None = Field(exclude=True)
37
+ assigned_software: SoftwareSchema | None
38
+ hardware: HardwareSchema | None
39
39
 
40
40
  feed: str | None
41
41
  progress: int | None
@@ -53,26 +53,6 @@ class DeviceSchema(BaseModel):
53
53
  def polling(self) -> bool | None:
54
54
  return self.last_seen < (self.poll_seconds + 10) if self.last_seen is not None else None
55
55
 
56
- @computed_field # type: ignore[misc]
57
- @property
58
- def sw_target_version(self) -> str | None:
59
- return self.assigned_software.version if self.assigned_software is not None else None
60
-
61
- @computed_field # type: ignore[misc]
62
- @property
63
- def sw_assigned(self) -> int | None:
64
- return self.assigned_software.id if self.assigned_software is not None else None
65
-
66
- @computed_field # type: ignore[misc]
67
- @property
68
- def hw_model(self) -> str | None:
69
- return self.hardware.model if self.hardware is not None else None
70
-
71
- @computed_field # type: ignore[misc]
72
- @property
73
- def hw_revision(self) -> str | None:
74
- return self.hardware.revision if self.hardware is not None else None
75
-
76
56
  @computed_field # type: ignore[misc]
77
57
  @property
78
58
  def poll_seconds(self) -> int:
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
4
 
5
- from pydantic import BaseModel, ConfigDict, Field, computed_field, field_serializer
5
+ from pydantic import BaseModel, ConfigDict, field_serializer
6
6
 
7
7
  from goosebit.schema.software import SoftwareSchema
8
8
 
@@ -14,21 +14,11 @@ class RolloutSchema(BaseModel):
14
14
  created_at: datetime
15
15
  name: str | None
16
16
  feed: str
17
- software: SoftwareSchema = Field(exclude=True)
17
+ software: SoftwareSchema
18
18
  paused: bool
19
19
  success_count: int
20
20
  failure_count: int
21
21
 
22
- @computed_field # type: ignore[misc]
23
- @property
24
- def sw_version(self) -> str:
25
- return self.software.version
26
-
27
- @computed_field # type: ignore[misc]
28
- @property
29
- def sw_file(self) -> str:
30
- return self.software.path.name
31
-
32
22
  @field_serializer("created_at")
33
23
  def serialize_created_at(self, created_at: datetime, _info):
34
24
  return int(created_at.timestamp() * 1000)
@@ -2,49 +2,206 @@ from .responses import DTColumnDescription
2
2
 
3
3
 
4
4
  class DeviceColumns:
5
- id = DTColumnDescription(title="ID", data="id", name="id", searchable=True, orderable=True)
6
- name = DTColumnDescription(title="Name", data="name", name="name", searchable=True, orderable=True)
7
- hw_model = DTColumnDescription(title="Model", data="hw_model")
8
- hw_revision = DTColumnDescription(title="Revision", data="hw_revision")
9
- feed = DTColumnDescription(title="Feed", data="feed", name="feed", searchable=True, orderable=True)
5
+ id = DTColumnDescription(
6
+ title="ID",
7
+ data="id",
8
+ name="id",
9
+ searchable=True,
10
+ orderable=True,
11
+ )
12
+ name = DTColumnDescription(
13
+ title="Name",
14
+ data="name",
15
+ name="name",
16
+ searchable=True,
17
+ orderable=True,
18
+ )
19
+ hw_model = DTColumnDescription(
20
+ title="Model",
21
+ data="hardware.model",
22
+ name="hardware__model",
23
+ searchable=True,
24
+ orderable=True,
25
+ )
26
+ hw_revision = DTColumnDescription(
27
+ title="Revision",
28
+ data="hardware.revision",
29
+ name="hardware__revision",
30
+ searchable=True,
31
+ orderable=True,
32
+ )
33
+ feed = DTColumnDescription(
34
+ title="Feed",
35
+ data="feed",
36
+ name="feed",
37
+ searchable=True,
38
+ orderable=True,
39
+ )
10
40
  sw_version = DTColumnDescription(
11
- title="Installed Software", data="sw_version", name="sw_version", searchable=True, orderable=True
41
+ title="Installed Software",
42
+ data="sw_version",
43
+ name="sw_version",
44
+ searchable=True,
45
+ orderable=True,
46
+ )
47
+ sw_target_version = DTColumnDescription(
48
+ title="Target Software",
49
+ data="assigned_software.version",
50
+ name="assigned_software__version",
51
+ searchable=True,
52
+ orderable=True,
12
53
  )
13
- sw_target_version = DTColumnDescription(title="Target Software", data="sw_target_version")
14
54
  update_mode = DTColumnDescription(
15
- title="Update Mode", data="update_mode", name="update_mode", searchable=True, orderable=True
55
+ title="Update Mode",
56
+ data="update_mode",
57
+ name="update_mode",
58
+ searchable=True,
59
+ orderable=True,
16
60
  )
17
61
  last_state = DTColumnDescription(
18
- title="State", data="last_state", name="last_state", searchable=True, orderable=True
62
+ title="State",
63
+ data="last_state",
64
+ name="last_state",
65
+ searchable=True,
66
+ orderable=True,
67
+ )
68
+ force_update = DTColumnDescription(
69
+ title="Force Update",
70
+ data="force_update",
71
+ name="force_update",
72
+ orderable=True,
73
+ )
74
+ progress = DTColumnDescription(
75
+ title="Progress",
76
+ data="progress",
77
+ name="progress",
78
+ orderable=True,
79
+ )
80
+ last_ip = DTColumnDescription(
81
+ title="Last IP",
82
+ data="last_ip",
83
+ name="last_ip",
84
+ searchable=True,
85
+ orderable=True,
86
+ )
87
+ polling = DTColumnDescription(
88
+ title="Polling",
89
+ data="polling",
90
+ )
91
+ last_seen = DTColumnDescription(
92
+ title="Last Seen",
93
+ data="last_seen",
94
+ name="last_seen",
95
+ orderable=True,
19
96
  )
20
- force_update = DTColumnDescription(title="Force Update", data="force_update")
21
- progress = DTColumnDescription(title="Progress", data="progress")
22
- last_ip = DTColumnDescription(title="Last IP", data="last_ip")
23
- polling = DTColumnDescription(title="Polling", data="polling")
24
- last_seen = DTColumnDescription(title="Last Seen", data="last_seen")
25
97
 
26
98
 
27
99
  class RolloutColumns:
28
- id = DTColumnDescription(title="ID", data="id", visible=False)
29
- created_at = DTColumnDescription(title="Created", data="created_at", name="created_at", orderable=True)
30
- name = DTColumnDescription(title="Name", data="name", name="name", searchable=True, orderable=True)
31
- feed = DTColumnDescription(title="Feed", data="feed", name="feed", searchable=True, orderable=True)
32
- sw_file = DTColumnDescription(title="Software File", data="sw_file", name="sw_file")
33
- sw_version = DTColumnDescription(title="Software Version", data="sw_version", name="sw_version")
34
- paused = DTColumnDescription(title="Paused", name="paused", data="paused")
35
- success_count = DTColumnDescription(title="Success Count", data="success_count", name="success_count")
36
- failure_count = DTColumnDescription(title="Failure Count", data="failure_count", name="failure_count")
100
+ id = DTColumnDescription(
101
+ title="ID",
102
+ data="id",
103
+ visible=False,
104
+ )
105
+ created_at = DTColumnDescription(
106
+ title="Created",
107
+ data="created_at",
108
+ name="created_at",
109
+ orderable=True,
110
+ )
111
+ name = DTColumnDescription(
112
+ title="Name",
113
+ data="name",
114
+ name="name",
115
+ searchable=True,
116
+ orderable=True,
117
+ )
118
+ feed = DTColumnDescription(
119
+ title="Feed",
120
+ data="feed",
121
+ name="feed",
122
+ searchable=True,
123
+ orderable=True,
124
+ )
125
+ sw_file = DTColumnDescription(
126
+ title="Software File",
127
+ data="software.name",
128
+ name="software__uri", # May cause strange orderings sorting by uri instead of the end of the path
129
+ searchable=True,
130
+ orderable=True,
131
+ )
132
+ sw_version = DTColumnDescription(
133
+ title="Software Version",
134
+ data="software.version",
135
+ name="software__version",
136
+ searchable=True,
137
+ orderable=True,
138
+ )
139
+ paused = DTColumnDescription(
140
+ title="Paused",
141
+ name="paused",
142
+ data="paused",
143
+ orderable=True,
144
+ )
145
+ success_count = DTColumnDescription(
146
+ title="Success Count",
147
+ data="success_count",
148
+ name="success_count",
149
+ orderable=True,
150
+ )
151
+ failure_count = DTColumnDescription(
152
+ title="Failure Count",
153
+ data="failure_count",
154
+ name="failure_count",
155
+ orderable=True,
156
+ )
37
157
 
38
158
 
39
159
  class SoftwareColumns:
40
- id = DTColumnDescription(title="ID", data="id", visible=False)
41
- name = DTColumnDescription(title="Name", data="name", name="name")
42
- version = DTColumnDescription(title="Version", data="version", name="version", searchable=True, orderable=True)
43
- compatibility = DTColumnDescription(title="Compatibility", name="compatibility", data="compatibility")
44
- size = DTColumnDescription(title="Size", name="size", data="size")
160
+ id = DTColumnDescription(
161
+ title="ID",
162
+ data="id",
163
+ visible=False,
164
+ )
165
+ name = DTColumnDescription(
166
+ title="Name",
167
+ data="name",
168
+ name="uri", # May cause strange orderings sorting by uri instead of the end of the path
169
+ searchable=True,
170
+ orderable=True,
171
+ )
172
+ version = DTColumnDescription(
173
+ title="Version",
174
+ data="version",
175
+ name="version",
176
+ searchable=True,
177
+ orderable=True,
178
+ )
179
+ compatibility = DTColumnDescription(
180
+ title="Compatibility",
181
+ name="compatibility",
182
+ data="compatibility",
183
+ )
184
+ size = DTColumnDescription(
185
+ title="Size",
186
+ name="size",
187
+ data="size",
188
+ orderable=True,
189
+ )
45
190
 
46
191
 
47
192
  class SettingsUsersColumns:
48
- username = DTColumnDescription(title="Username", data="username", searchable=True, orderable=True)
49
- enabled = DTColumnDescription(title="Enabled", data="enabled")
50
- permissions = DTColumnDescription(title="Permissions", data="permissions")
193
+ username = DTColumnDescription(
194
+ title="Username",
195
+ data="username",
196
+ searchable=True,
197
+ orderable=True,
198
+ )
199
+ enabled = DTColumnDescription(
200
+ title="Enabled",
201
+ data="enabled",
202
+ orderable=True,
203
+ )
204
+ permissions = DTColumnDescription(
205
+ title="Permissions",
206
+ data="permissions",
207
+ )
@@ -37,10 +37,14 @@ async def devices_get(dt_query: Annotated[DataTableRequest, Depends(parse_datata
37
37
  return (
38
38
  Q(id__icontains=search_value)
39
39
  | Q(name__icontains=search_value)
40
+ | Q(hardware__model__icontains=search_value)
41
+ | Q(hardware__revision__icontains=search_value)
40
42
  | Q(feed__icontains=search_value)
41
43
  | Q(sw_version__icontains=search_value)
44
+ | Q(assigned_software__version__icontains=search_value)
42
45
  | Q(update_mode=int(UpdateModeEnum.from_str(search_value)))
43
46
  | Q(last_state=int(UpdateStateEnum.from_str(search_value)))
47
+ | Q(last_ip__icontains=search_value)
44
48
  )
45
49
 
46
50
  query = Device.all().prefetch_related("assigned_software", "hardware", "assigned_software__compatibility")
@@ -23,7 +23,12 @@ router = APIRouter(prefix="/rollouts")
23
23
  )
24
24
  async def rollouts_get(dt_query: Annotated[DataTableRequest, Depends(parse_datatables_query)]) -> BFFRolloutsResponse:
25
25
  def search_filter(search_value):
26
- return Q(name__icontains=search_value) | Q(feed__icontains=search_value)
26
+ return (
27
+ Q(name__icontains=search_value)
28
+ | Q(feed__icontains=search_value)
29
+ | Q(software__uri__icontains=search_value)
30
+ | Q(software__version__icontains=search_value)
31
+ )
27
32
 
28
33
  query = Rollout.all().prefetch_related("software", "software__compatibility")
29
34
 
@@ -5,7 +5,8 @@ from tortoise.expressions import Q
5
5
  from tortoise.queryset import QuerySet
6
6
 
7
7
  from goosebit.schema.software import SoftwareSchema
8
- from goosebit.ui.bff.common.requests import DataTableOrderDirection, DataTableRequest
8
+
9
+ from ..common.requests import DataTableOrderDirection, DataTableRequest
9
10
 
10
11
 
11
12
  class BFFSoftwareResponse(BaseModel):
@@ -41,7 +42,6 @@ class BFFSoftwareResponse(BaseModel):
41
42
  query = query.limit(dt_query.length)
42
43
 
43
44
  software = await query.offset(dt_query.start).all()
44
-
45
45
  data = [SoftwareSchema.model_validate(s) for s in software]
46
46
 
47
47
  return cls(data=data, draw=dt_query.draw, records_total=total_records, records_filtered=filtered_records)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: goosebit
3
- Version: 0.2.9
3
+ Version: 0.2.10
4
4
  Summary: A simplistic, opinionated remote update server implementing hawkBit™'s DDI API
5
5
  Author: Brett Rowan
6
6
  Author-email: 121075405+b-rowan@users.noreply.github.com
@@ -98,8 +98,8 @@ The software packages managed by gooseBit are either stored on the local filesys
98
98
 
99
99
  ## Assumptions
100
100
 
101
- - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://github.com/rauc/rauc) + [RAUC hawkBit Updater](https://github.com/rauc/rauc-hawkbit-updater) for managing software updates.
102
- - Devices send certain attributes (`sw_version`, `hw_model`, `hw_revision`).
101
+ - Devices use [SWUpdate](https://swupdate.org) or [RAUC](https://rauc.io) + [RAUC hawkBit Updater](https://rauc-hawkbit-updater.readthedocs.io) for managing software updates.
102
+ - Devices send certain attributes (`sw_version`, `hw_boardname`, `hw_revision`).
103
103
  - Semantic versions are used.
104
104
  - With RAUC and multiple hardware revisions, `compatible` in `manifest.raucm` is set to something like `my-board-rev4.2` or `Some Board 2b`.
105
105
 
@@ -109,7 +109,7 @@ The software packages managed by gooseBit are either stored on the local filesys
109
109
 
110
110
  When a device connects to gooseBit for the first time, it is automatically added to the device registry. The server will then request the device's configuration data, including:
111
111
 
112
- - `hw_model` and `hw_revision`: Used to match compatible software.
112
+ - `hw_boardname` and `hw_revision`: Used to match compatible software.
113
113
  - `sw_version`: Indicates the currently installed software version.
114
114
 
115
115
  The registry tracks each device's status, including the last online timestamp, installed software version, update state, and more.
@@ -51,9 +51,9 @@ goosebit/db/pg_ssl_context.py,sha256=OyNJBYPLb_yRpA3AaesYr3bro9R3_20fzcAFUUTl00c
51
51
  goosebit/device_manager.py,sha256=UwAslhSk6FEt2cJOMujj6enfmSR-KPrNoAeSCa56Zpg,9284
52
52
  goosebit/plugins/__init__.py,sha256=9VLjGc2F72teF9dxGGkwDXTbL0Q1wbjLTheb4hY1qEg,1185
53
53
  goosebit/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- goosebit/schema/devices.py,sha256=4LBYGnceK2IWQFhcIEMYC7bLlHPoTYO0ciKcnUnwSkA,2787
54
+ goosebit/schema/devices.py,sha256=pfhUlsd4SaluBBWrZrHRerEfEw4SVXWP2TqdAIazDag,2007
55
55
  goosebit/schema/plugins.py,sha256=jJFQ-o6QY04YQPz-ovCpnMf-yKlEmoZqq3gJlHUJJ1I,2281
56
- goosebit/schema/rollouts.py,sha256=Kp--XRC39SDs1bKf59q8fBHzitoW88ZMN1GVlbCQotQ,882
56
+ goosebit/schema/rollouts.py,sha256=uRRuLalello11Qe7qzeXlVz-9kEjqMK0UFS650TDQrU,584
57
57
  goosebit/schema/software.py,sha256=W02rA0guQ7zeeVMTdwxt6EjCnTdf-9JewVJRqdN_GK0,951
58
58
  goosebit/schema/updates.py,sha256=aZdNAfXZote6JxgH1Ut0YZMCLlOmtBz3Ia3nXRtxfQA,343
59
59
  goosebit/schema/users.py,sha256=ZKp4eHh4EH0XRZcmpw7exZO-ypcDmzAtJXJ7zVSbans,190
@@ -67,7 +67,7 @@ goosebit/storage/s3.py,sha256=buvLjn10AHRvI48-OfYbppcRVyjq3z2C-PvZvt94XX8,3627
67
67
  goosebit/ui/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
68
68
  goosebit/ui/bff/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
69
69
  goosebit/ui/bff/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- goosebit/ui/bff/common/columns.py,sha256=NiHPjStNz4eZH2RlMvI6fPYZXd5oLTqP8NXG84iOAd4,3026
70
+ goosebit/ui/bff/common/columns.py,sha256=Q7c8FQ_z5bMAfoIlNwmUZAJ-vWQXqS7geG0H7HGf0UE,4972
71
71
  goosebit/ui/bff/common/requests.py,sha256=Db8AohkRfsjUbx3pbdKVva7ZkLhAfBiDwAA221OXd5M,1183
72
72
  goosebit/ui/bff/common/responses.py,sha256=DKEvkpOsFcOkUmYaF1YDqElEOFIqV-uH9yUd5e4e2ak,335
73
73
  goosebit/ui/bff/common/util.py,sha256=_hz89EFLAL1UvbIvJJJSF80PL4T1mz1Vk7354wHBzOE,1144
@@ -76,12 +76,12 @@ goosebit/ui/bff/devices/device/__init__.py,sha256=kzt5TBA-bJmDZFXYPohggbMOW7Ghkl
76
76
  goosebit/ui/bff/devices/device/routes.py,sha256=d3ZwswAPR5J8CvbjmJ8gH9KtXTHfZmSFR5txufLtCEU,495
77
77
  goosebit/ui/bff/devices/requests.py,sha256=DRt8gz8TFpgCsaevDc_s-V2XKfDwHHirXE-LOuiMPZU,320
78
78
  goosebit/ui/bff/devices/responses.py,sha256=4279xeu-soqgyOc4ncKZpai6juBQ3dl096p2LgtIu2s,1208
79
- goosebit/ui/bff/devices/routes.py,sha256=ljvIgN2MGJv_j59YPNoeSIC5w5kBc6hvfDagF0GbLNQ,5093
79
+ goosebit/ui/bff/devices/routes.py,sha256=aFZvu55GdgZHCWrJ0SFY0-LWFKY_2Bord7OrvWieOi0,5327
80
80
  goosebit/ui/bff/download/__init__.py,sha256=kzt5TBA-bJmDZFXYPohggbMOW7GhklyflaRKZNC0yDY,42
81
81
  goosebit/ui/bff/download/routes.py,sha256=zaGZmHBUGRwxKTjDfpr151Yt1fpC803b1rj25PvxE-Y,1126
82
82
  goosebit/ui/bff/rollouts/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
83
83
  goosebit/ui/bff/rollouts/responses.py,sha256=gFEzWkFUBIka98lrA0ivdXBiTqaU5AugfJm2F3p33uk,1180
84
- goosebit/ui/bff/rollouts/routes.py,sha256=kxuV_wW1xIS4UzWAw47ibJ7XNcRK5c90eA2AyVftSNU,2533
84
+ goosebit/ui/bff/rollouts/routes.py,sha256=lLOSK33FKsi5H3rue4thKCuA0oCaB6Pl58YiJbbT6AA,2683
85
85
  goosebit/ui/bff/routes.py,sha256=V-C-WS92PvhT6SJJzezF1t6M7w8e_lWsvZE-g5n7w1Y,477
86
86
  goosebit/ui/bff/settings/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
87
87
  goosebit/ui/bff/settings/routes.py,sha256=5WOlsPg552pb9tSrKlAw3FbEW734hGCfT5zGMxkatCg,594
@@ -89,7 +89,7 @@ goosebit/ui/bff/settings/users/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH
89
89
  goosebit/ui/bff/settings/users/responses.py,sha256=_y-qVOQlZjiY-Ru4ejh_LxoR6u8tkR572CyNbe2wOmw,1173
90
90
  goosebit/ui/bff/settings/users/routes.py,sha256=YlAWOcRmmeeaUGzu4ZNyu1yELbyFQkvY8fJiUD79WAQ,2548
91
91
  goosebit/ui/bff/software/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
92
- goosebit/ui/bff/software/responses.py,sha256=e7zMP8q2uWgKRy1q5Jp0HTNx-lggljOy2BFQRJglDSo,1920
92
+ goosebit/ui/bff/software/responses.py,sha256=Xc16AqB6W8NQzfSI7DBsOHPMohpva7QOfm9zIht4n7g,1906
93
93
  goosebit/ui/bff/software/routes.py,sha256=rBD7rDFr4QsnOHRhrY_92b2vjoBcTcCciHFMJV090Q0,4123
94
94
  goosebit/ui/nav.py,sha256=4s-SoIIYhJxOeTSsxnkbzErSzIkgwIUO-1ubc4ayemI,561
95
95
  goosebit/ui/routes.py,sha256=DuRh-RAahamL4E6p_NaXW2nDWGGIyLL611KCRhhf6O8,3720
@@ -130,8 +130,8 @@ goosebit/users/__init__.py,sha256=fmoq3LtDFk0nKUaJyvOFunRMSMiUvEgRQYu56BcGlo8,21
130
130
  goosebit/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
131
  goosebit/util/path.py,sha256=Ir6h3C_kfsVDbzt0icHhH3zDhLnEdW7AeKN0BkjeIJY,1584
132
132
  goosebit/util/version.py,sha256=dLBOn8Pb3CeIHhTXYxRfDE3fWGoAl0LPjCTF_xHGFzo,3137
133
- goosebit-0.2.9.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
134
- goosebit-0.2.9.dist-info/METADATA,sha256=Y9jzIsB4sOahUb2HV6sCFuTJeBR3uAtLrlcDGXw6PFk,8754
135
- goosebit-0.2.9.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
136
- goosebit-0.2.9.dist-info/entry_points.txt,sha256=5p3wNB9_WEljksEBgZmOxO0DrBVhRxP20JD9JJ_lpb4,57
137
- goosebit-0.2.9.dist-info/RECORD,,
133
+ goosebit-0.2.10.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
134
+ goosebit-0.2.10.dist-info/METADATA,sha256=f0d8bVWfxoCPI5aC_nJ4jAq7MPb1EnMv5cEvimev8dI,8749
135
+ goosebit-0.2.10.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
136
+ goosebit-0.2.10.dist-info/entry_points.txt,sha256=5p3wNB9_WEljksEBgZmOxO0DrBVhRxP20JD9JJ_lpb4,57
137
+ goosebit-0.2.10.dist-info/RECORD,,