roboherd 0.1.2__py3-none-any.whl → 0.1.4__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.

Potentially problematic release.


This version of roboherd might be problematic. Click here for more details.

roboherd/__main__.py CHANGED
@@ -10,6 +10,7 @@ from roboherd.herd import RoboHerd
10
10
  from roboherd.herd.manager import HerdManager
11
11
  from roboherd.util import create_connection
12
12
  from roboherd.register import register as run_register
13
+ from roboherd.validators import validators
13
14
 
14
15
  logging.basicConfig(level=logging.INFO)
15
16
 
@@ -32,6 +33,7 @@ def main(ctx, connection_string, base_url, config_file):
32
33
  settings = dynaconf.Dynaconf(
33
34
  settings_files=[config_file],
34
35
  envvar_prefix="ROBOHERD",
36
+ validators=validators,
35
37
  )
36
38
  ctx.ensure_object(dict)
37
39
 
@@ -41,12 +43,12 @@ def main(ctx, connection_string, base_url, config_file):
41
43
  if connection_string:
42
44
  ctx.obj["connection_string"] = connection_string
43
45
  else:
44
- ctx.obj["connection_string"] = settings.get("connection_string")
46
+ ctx.obj["connection_string"] = settings.connection_string
45
47
 
46
48
  if base_url:
47
49
  ctx.obj["base_url"] = base_url
48
50
  else:
49
- ctx.obj["base_url"] = settings.get("base_url")
51
+ ctx.obj["base_url"] = settings.base_url
50
52
 
51
53
 
52
54
  @main.command()
@@ -5,11 +5,11 @@ from almabtrieb import Almabtrieb
5
5
 
6
6
 
7
7
  def get_raw(data: dict) -> dict:
8
- return data.get("data").get("raw")
8
+ return data.get("data", {}).get("raw")
9
9
 
10
10
 
11
11
  def get_parsed(data: dict) -> dict:
12
- result = data.get("data").get("parsed")
12
+ result = data.get("data", {}).get("parsed")
13
13
  if result is None:
14
14
  raise ValueError("No parsed data found")
15
15
  return result
@@ -23,11 +23,17 @@ ParsedData = Annotated[dict, Depends(get_parsed)]
23
23
 
24
24
 
25
25
  def get_activity(parsed: ParsedData) -> dict:
26
- return parsed.get("activity")
26
+ result = parsed.get("activity")
27
+ if not result:
28
+ raise ValueError("No activity found")
29
+ return result
27
30
 
28
31
 
29
32
  def get_embedded_object(parsed: ParsedData) -> dict:
30
- return parsed.get("embeddedObject")
33
+ result = parsed.get("embeddedObject")
34
+ if not result:
35
+ raise ValueError("No embedded object found")
36
+ return result
31
37
 
32
38
 
33
39
  Activity = Annotated[dict, Depends(get_activity)]
@@ -7,19 +7,19 @@ from .common import Profile
7
7
  try:
8
8
  from bovine.activitystreams import factories_for_actor_object
9
9
  from bovine.activitystreams.activity_factory import (
10
- ActivityFactory as BovineActivityFactory,
10
+ ActivityFactory as BovineActivityFactory, # type: ignore
11
11
  )
12
12
  from bovine.activitystreams.object_factory import (
13
- ObjectFactory as BovineObjectFactory,
13
+ ObjectFactory as BovineObjectFactory, # type: ignore
14
14
  )
15
15
 
16
- def get_activity_factory(profile: Profile) -> BovineActivityFactory:
16
+ def get_activity_factory(profile: Profile) -> BovineActivityFactory: # type: ignore
17
17
  activity_factory, _ = factories_for_actor_object(profile)
18
- return activity_factory
18
+ return activity_factory # type: ignore
19
19
 
20
- def get_object_factory(profile: Profile) -> BovineObjectFactory:
20
+ def get_object_factory(profile: Profile) -> BovineObjectFactory: # type: ignore
21
21
  _, object_factory = factories_for_actor_object(profile)
22
- return object_factory
22
+ return object_factory # type: ignore
23
23
 
24
24
  except ImportError:
25
25
 
@@ -34,8 +34,8 @@ except ImportError:
34
34
  raise ImportError("bovine not installed")
35
35
 
36
36
 
37
- ActivityFactory = Annotated[BovineActivityFactory, Depends(get_activity_factory)]
37
+ ActivityFactory = Annotated[BovineActivityFactory, Depends(get_activity_factory)] # type: ignore
38
38
  """The activity factory of type [bovine.activitystreams.activity_factory.ActivityFactory][]"""
39
39
 
40
- ObjectFactory = Annotated[BovineObjectFactory, Depends(get_object_factory)]
40
+ ObjectFactory = Annotated[BovineObjectFactory, Depends(get_object_factory)] # type: ignore
41
41
  """The object factory of type [bovine.activitystreams.object_factory.ObjectFactory][]"""
@@ -5,6 +5,8 @@ from roboherd.cow import RoboCow
5
5
 
6
6
 
7
7
  def get_profile(cow: RoboCow) -> dict:
8
+ if cow.profile is None:
9
+ raise ValueError("Cow has no profile")
8
10
  return cow.profile
9
11
 
10
12
 
roboherd/cow/__init__.py CHANGED
@@ -187,7 +187,11 @@ class RoboCow:
187
187
  """Runs when the cow is birthed"""
188
188
 
189
189
  if self.profile is None:
190
+ if not self.actor_id:
191
+ raise ValueError("Actor ID is not set")
190
192
  result = await connection.fetch(self.actor_id, self.actor_id)
193
+ if not result.data:
194
+ raise ValueError("Could not retrieve profile")
191
195
  self.profile = result.data
192
196
 
193
197
  if self.cron_entries:
roboherd/cow/profile.py CHANGED
@@ -1,5 +1,15 @@
1
1
  from urllib.parse import urlparse
2
- from bovine.activitystreams.utils import as_list
2
+
3
+ try:
4
+ from bovine.activitystreams.utils import as_list
5
+ except ImportError:
6
+
7
+ def as_list(value):
8
+ if isinstance(value, list):
9
+ return value
10
+
11
+ return [value]
12
+
3
13
 
4
14
  from .types import Information
5
15
 
@@ -27,7 +37,7 @@ def key_index_from_attachment(attachments: list[dict], key: str) -> int | None:
27
37
 
28
38
 
29
39
  def determine_action_for_key_and_value(
30
- attachments: list[dict], key: str, value: str
40
+ attachments: list[dict], key: str, value: str | None
31
41
  ) -> dict | None:
32
42
  idx = key_index_from_attachment(attachments, key)
33
43
  if idx is None:
@@ -78,19 +88,19 @@ def determine_actions(information: Information, profile: dict) -> list[dict] | N
78
88
  "identifier": "acct:"
79
89
  + information.handle
80
90
  + "@"
81
- + urlparse(profile.get("id")).netloc,
91
+ + str(urlparse(profile.get("id")).netloc),
82
92
  "primary": True,
83
93
  }
84
94
  )
85
95
 
86
- actions = list(filter(lambda x: x, actions))
96
+ actions = [x for x in actions if x is not None]
87
97
 
88
98
  if len(actions) == 0:
89
99
  return None
90
100
  return actions
91
101
 
92
102
 
93
- def determine_profile_update(information: Information, profile: dict) -> dict:
103
+ def determine_profile_update(information: Information, profile: dict) -> dict | None:
94
104
  """Returns the update for the profile"""
95
105
 
96
106
  update = {"actor": profile.get("id")}
roboherd/cow/types.py CHANGED
@@ -6,13 +6,13 @@ class MetaInformation(BaseModel):
6
6
  information such as the author and the source repository"""
7
7
 
8
8
  source: str | None = Field(
9
- None,
9
+ default=None,
10
10
  examples=["https://forge.example/repo"],
11
11
  description="The source repository",
12
12
  )
13
13
 
14
14
  author: str | None = Field(
15
- None,
15
+ default=None,
16
16
  examples=["acct:author@domain.example"],
17
17
  description="The author, often a Fediverse handle",
18
18
  )
@@ -22,23 +22,25 @@ class Information(BaseModel):
22
22
  """Information about the cow"""
23
23
 
24
24
  type: str = Field(
25
- "Service", examples=["Service"], description="ActivityPub type of the actor."
25
+ default="Service",
26
+ examples=["Service"],
27
+ description="ActivityPub type of the actor.",
26
28
  )
27
29
 
28
30
  handle: str | None = Field(
29
- None,
31
+ default=None,
30
32
  examples=["moocow"],
31
33
  description="Used as the handle in `acct:handle@domain.example`",
32
34
  )
33
35
 
34
36
  name: str | None = Field(
35
- None,
37
+ default=None,
36
38
  examples=["The mooing cow 🐮"],
37
39
  description="The display name of the cow",
38
40
  )
39
41
 
40
42
  description: str | None = Field(
41
- None,
43
+ default=None,
42
44
  examples=[
43
45
  "I'm a cow that moos.",
44
46
  """<p>An example bot to illustrate Roboherd</p><p>For more information on RoboHerd, see <a href="https://codeberg.org/bovine/roboherd">its repository</a>.</p>""",
@@ -47,12 +49,12 @@ class Information(BaseModel):
47
49
  )
48
50
 
49
51
  frequency: str | None = Field(
50
- None,
52
+ default=None,
51
53
  examples=["daily"],
52
54
  description="Frequency of posting. Is set automatically if cron expressions are used.",
53
55
  )
54
56
 
55
57
  meta_information: MetaInformation = Field(
56
- MetaInformation(),
58
+ default=MetaInformation(),
57
59
  description="Meta information about the cow, such as the source repository",
58
60
  )
roboherd/cow/util.py CHANGED
@@ -19,5 +19,8 @@ async def call_handler(
19
19
  cow=None,
20
20
  ):
21
21
  return await inject(handler_info.func)(
22
- data=data, connection=connection, actor_id=actor_id, cow=cow
22
+ data=data, # type: ignore
23
+ connection=connection,
24
+ actor_id=actor_id,
25
+ cow=cow,
23
26
  )
@@ -45,7 +45,7 @@ async def create(
45
45
  raw: RawData, publish_object: PublishObject, object_factory: ObjectFactory
46
46
  ):
47
47
  note = (
48
- object_factory.reply(
48
+ object_factory.reply( # type: ignore
49
49
  raw.get("object"),
50
50
  content=reply_content(raw),
51
51
  )
@@ -51,7 +51,7 @@ async def post_number(
51
51
  ):
52
52
  number = random.randint(0, 1000)
53
53
 
54
- note = factory.note(content=f"Number: {number}").as_public().build()
54
+ note = factory.note(content=f"Number: {number}").as_public().build() # type: ignore
55
55
  await publisher(note)
56
56
 
57
57
  handle = "even" if number % 2 == 0 else "odd"
@@ -18,5 +18,5 @@ bot = RoboCow(
18
18
  @bot.cron("42 * * * *")
19
19
  async def crow(publisher: PublishObject, object_factory: ObjectFactory):
20
20
  await publisher(
21
- object_factory.note(content="cock-a-doodle-doo").as_public().build()
21
+ object_factory.note(content="cock-a-doodle-doo").as_public().build() # type: ignore
22
22
  )
@@ -18,4 +18,4 @@ bot = RoboCow(
18
18
 
19
19
  @bot.startup
20
20
  async def startup(publish_object: PublishObject, object_factory: ObjectFactory):
21
- await publish_object(object_factory.note(content="Booo! 🐦").as_public().build())
21
+ await publish_object(object_factory.note(content="Booo! 🐦").as_public().build()) # type: ignore
roboherd/herd/__init__.py CHANGED
@@ -29,6 +29,9 @@ class RoboHerd:
29
29
  await self.process(connection)
30
30
 
31
31
  async def startup(self, connection: Almabtrieb):
32
+ if not connection.information:
33
+ raise Exception("Could not get information from server")
34
+
32
35
  self.cows = self.manager.existing_cows(connection.information.actors)
33
36
 
34
37
  cows_to_create = self.manager.cows_to_create(connection.information.actors)
@@ -60,9 +63,6 @@ class RoboHerd:
60
63
  scheduler = HerdScheduler(self.cron_entries(), connection)
61
64
  scheduler.create_task(tg)
62
65
 
63
- def introduce(self, cow: RoboCow):
64
- self.manager.add_to_herd(cow)
65
-
66
66
  def validate(self, connection):
67
67
  result = connection.information
68
68
 
@@ -43,4 +43,6 @@ class HerdManager:
43
43
  }
44
44
  names_to_create = self.herd_config.names - existing_names
45
45
 
46
- return {self.herd_config.for_name(name) for name in names_to_create}
46
+ cows = {self.herd_config.for_name(name) for name in names_to_create}
47
+
48
+ return {cow for cow in cows if cow}
@@ -21,7 +21,7 @@ def test_config():
21
21
  },
22
22
  },
23
23
  }
24
- )
24
+ ) # type: ignore
25
25
  return config
26
26
 
27
27
 
@@ -44,7 +44,7 @@ def test_load_config(test_config):
44
44
  assert len(herd.cows) == 2
45
45
 
46
46
  moocow = herd.for_name("moocow")
47
-
47
+ assert moocow
48
48
  assert moocow.name == "moocow"
49
49
 
50
50
 
@@ -21,7 +21,7 @@ def test_config():
21
21
  },
22
22
  },
23
23
  }
24
- )
24
+ ) # type: ignore
25
25
  return config
26
26
 
27
27
 
@@ -0,0 +1,10 @@
1
+ from dynaconf import Dynaconf
2
+
3
+ from .validators import validators
4
+
5
+
6
+ def test_validators():
7
+ settings = Dynaconf(validators=validators)
8
+
9
+ assert settings.base_url is None
10
+ assert settings.connection_string is None
roboherd/util.py CHANGED
@@ -4,7 +4,6 @@ import copy
4
4
  import importlib
5
5
  from importlib import import_module
6
6
  from urllib.parse import parse_qs, urlparse
7
-
8
7
  from almabtrieb import Almabtrieb
9
8
 
10
9
  from roboherd.cow import RoboCow
roboherd/validators.py ADDED
@@ -0,0 +1,6 @@
1
+ from dynaconf import Validator
2
+
3
+ validators = [
4
+ Validator("base_url", default=None),
5
+ Validator("connection_string", default=None),
6
+ ]
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roboherd
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: A Fediverse bot framework
5
5
  Requires-Python: >=3.11
6
+ Requires-Dist: aiohttp>=3.11.12
6
7
  Requires-Dist: almabtrieb[mqtt]>=0.1.0a1
7
8
  Requires-Dist: apscheduler>=3.11.0
8
9
  Requires-Dist: click>=8.1.8
@@ -0,0 +1,42 @@
1
+ roboherd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ roboherd/__main__.py,sha256=cY4f-39QCDhStJ4gDuuSz46RDFE_AKnu08sTCpQEEV4,2933
3
+ roboherd/register.py,sha256=Gqa5aT2supVJMj7z21btMYRma3_WW0oK5gjZftr048s,976
4
+ roboherd/test_util.py,sha256=Yor_YgXtvK3WnZu6jr7DvNtTLdR9YWHCA5QufHo_w2s,535
5
+ roboherd/test_validators.py,sha256=UiFgJkutmXBLjGpdLP2IBYCEf75quwnRHX7Z51G8Xqo,222
6
+ roboherd/util.py,sha256=xgOpGwgvj4QY-m687H7EcDPfIF-pFgdmCsYPmeK13to,3064
7
+ roboherd/validators.py,sha256=2mc43ZGwFazp4f3B9J4RxZCU4Y_ErSNotib8MnYVtmY,140
8
+ roboherd/annotations/__init__.py,sha256=z7Q-NwHtGm35AUcuc4SxmWGFLVQxCFhYNJlzOc2kdOY,1610
9
+ roboherd/annotations/bovine.py,sha256=qXkliFVT63BfGn820Bopwd7O41ofP7VbNomxyit4zBg,1494
10
+ roboherd/annotations/common.py,sha256=aeoWDEpWdX3llc-CiuifT4A8_Ote29PkELqOkF9Dy5o,314
11
+ roboherd/cow/__init__.py,sha256=qS5ztkVa-vza6f-kZyn4fS5LVa4Fu5c083FyBcAEQC4,6051
12
+ roboherd/cow/handlers.py,sha256=k5Tc1M--wqmZ2EZvzIfID4dp8XE0rN18puMTKkNVjjE,1491
13
+ roboherd/cow/profile.py,sha256=NxnLdQYwOIjzZLu2iYEMMQyTOdUsGpLRe5nIN_jo-14,3223
14
+ roboherd/cow/test_handlers.py,sha256=SwrZZcU_BD2BpJUFg18mFEsyUqu7N81-MkjIaGv7whQ,1673
15
+ roboherd/cow/test_init.py,sha256=Te-4Z8lPpMlSv99OkzPLMtB607NSOfdRD3EB-6_3n1A,1370
16
+ roboherd/cow/test_profile.py,sha256=edWKVL8VmOb8XtE1OQmwDLuw4mcDtxMKBfA9Kbd71qU,1423
17
+ roboherd/cow/test_util.py,sha256=8FLRtVdSMmIo6NSpCpB9mS0PwOCpGgUeDAA1q6Gv0P4,430
18
+ roboherd/cow/types.py,sha256=p2-7p936mm9E9slGnYbei-pui8FeMCNIuomLHcE7BuE,1790
19
+ roboherd/cow/util.py,sha256=ASQn7AnSl5lskECqCyqOKn5BYC8yOces4FK3uNV8010,534
20
+ roboherd/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ roboherd/examples/dev_null.py,sha256=6SZ9wlcawSBqhdq6Zv4xPXH5eKH2g1VaRwv3hSCDucE,308
22
+ roboherd/examples/json_echo.py,sha256=EFqNwaSKs0hTQjKZVatjn6i3O7rQff2GTHnEfpL1ha0,1370
23
+ roboherd/examples/meta.py,sha256=tFhHe-DJn2J13Mm22f-gFm5I8_3uQwLU4mAkrK2xzEM,170
24
+ roboherd/examples/moocow.py,sha256=OkceeaRqkjR31Nue8anHtL_DMqd7finLzs-gUaKsVBo,1083
25
+ roboherd/examples/number.py,sha256=Sj9aYfdtzANUfWVJnoX73zEvDNVcdrr-STZDSwNRHlI,2003
26
+ roboherd/examples/rooster.py,sha256=5_rPGLQTLv1s0cyE6l7WXLum-QLpQZ2p63YBkfrxKFw,596
27
+ roboherd/examples/scarecrow.py,sha256=gLbQFx7Hu0W0H3_d9yi0mAO4drXxBshM8Iwoc-NdrjY,633
28
+ roboherd/herd/__init__.py,sha256=nhGfHkuAErP7MDh44IbfsonMd0UKeK8GqaHkEUAsZtc,3012
29
+ roboherd/herd/builder.py,sha256=MSVPRF0Jsxure9kdyCoYJHQ7nYilGAD0_uQaGQ-rQyE,619
30
+ roboherd/herd/processor.py,sha256=NkROTAPs6ZoYW_0TSDnNkAfos4cTnaFgwtW3wOFSgQY,1022
31
+ roboherd/herd/scheduler.py,sha256=fkR-74bFZ73DmlJje_dQSytxnFFLV5hCa067mXdwvXs,1266
32
+ roboherd/herd/test_herd.py,sha256=sQkzGCWdFveLklhaOJUybtl7odO-QOSDdd-_gan1py8,845
33
+ roboherd/herd/test_scheduler.py,sha256=wLisqRMSl734P_rjbqMNH5WTQKepwihgr7ZC32nEj80,424
34
+ roboherd/herd/types.py,sha256=_EidQbglm0jpsKX1EsL6U2qm_J5wCPhwUi6Avac22Ow,210
35
+ roboherd/herd/manager/__init__.py,sha256=yDVeSyJ3vIn9RMKR0FlobQA81oOQgdov5VVOIUAMwws,1454
36
+ roboherd/herd/manager/config.py,sha256=qfcED9PfzKzDCWaYHefYj8AImcsOFs5daGpJwUrXlV4,1313
37
+ roboherd/herd/manager/test_config.py,sha256=YQ-3huCZfHDqt2mdGjLs0ck5-DOkKdjKEzT3uhX0sLk,1293
38
+ roboherd/herd/manager/test_manager.py,sha256=9pSMaH7zmN-zagYCIBpQcV3Q0sBT7XZSCvsmLVC0rOI,1047
39
+ roboherd-0.1.4.dist-info/METADATA,sha256=55W2-6U-lsE1mibBgc9XaEx1Elo0BEQJTSxCxHWVvN0,830
40
+ roboherd-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
41
+ roboherd-0.1.4.dist-info/entry_points.txt,sha256=WebdVUmh8Ot-FupKJY6Du8LuFbmezt9yoy2UICqV3bE,52
42
+ roboherd-0.1.4.dist-info/RECORD,,
@@ -1,40 +0,0 @@
1
- roboherd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- roboherd/__main__.py,sha256=y2Ge8zajHn4rB4SlunLzmH5MNMCxklrhTaDdMbujjq8,2873
3
- roboherd/register.py,sha256=Gqa5aT2supVJMj7z21btMYRma3_WW0oK5gjZftr048s,976
4
- roboherd/test_util.py,sha256=Yor_YgXtvK3WnZu6jr7DvNtTLdR9YWHCA5QufHo_w2s,535
5
- roboherd/util.py,sha256=23X_-CiJoW6xd36YhTzIkXoS3y_eN5ILJDCC0GnBhm0,3065
6
- roboherd/annotations/__init__.py,sha256=hdW1HypuV6duCYxEhR2a9eidgcrC5-oAM-hHyzVh10E,1425
7
- roboherd/annotations/bovine.py,sha256=3LnS19pJ6Z1pSB50IaTxDnvaPlU_4qp_lFyQjAtJ5P0,1366
8
- roboherd/annotations/common.py,sha256=xr8FanMMPA1DDnCdguY4DLG9DbqmziaZxNR4-ww2ewk,239
9
- roboherd/cow/__init__.py,sha256=j6a1i_kAndo71Ufoy1bZr1FC9othg-cz-6x9z5yQ75E,5866
10
- roboherd/cow/handlers.py,sha256=k5Tc1M--wqmZ2EZvzIfID4dp8XE0rN18puMTKkNVjjE,1491
11
- roboherd/cow/profile.py,sha256=XEFU8wJYVQxrlbAhUWZSDhfxBn1IXm_6f8YBlpHvUjM,3060
12
- roboherd/cow/test_handlers.py,sha256=SwrZZcU_BD2BpJUFg18mFEsyUqu7N81-MkjIaGv7whQ,1673
13
- roboherd/cow/test_init.py,sha256=Te-4Z8lPpMlSv99OkzPLMtB607NSOfdRD3EB-6_3n1A,1370
14
- roboherd/cow/test_profile.py,sha256=edWKVL8VmOb8XtE1OQmwDLuw4mcDtxMKBfA9Kbd71qU,1423
15
- roboherd/cow/test_util.py,sha256=8FLRtVdSMmIo6NSpCpB9mS0PwOCpGgUeDAA1q6Gv0P4,430
16
- roboherd/cow/types.py,sha256=GtDnvpiH0w-Ux6BkhjNOgRdZ9YOITPB16BZd51MzKfA,1709
17
- roboherd/cow/util.py,sha256=oBytl3cOhYgZCCnihM3wkMxG8xQZUlohVSxCaaHDsYc,493
18
- roboherd/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- roboherd/examples/dev_null.py,sha256=6SZ9wlcawSBqhdq6Zv4xPXH5eKH2g1VaRwv3hSCDucE,308
20
- roboherd/examples/json_echo.py,sha256=vOwbCX7apXh87RNFdwDWZXaIpJuJO5Tcsck_9qjRpqw,1354
21
- roboherd/examples/meta.py,sha256=tFhHe-DJn2J13Mm22f-gFm5I8_3uQwLU4mAkrK2xzEM,170
22
- roboherd/examples/moocow.py,sha256=OkceeaRqkjR31Nue8anHtL_DMqd7finLzs-gUaKsVBo,1083
23
- roboherd/examples/number.py,sha256=U71mcmLVqtOkl6vkudHKlJmxmLVCI11q1ekQOoQfTag,1987
24
- roboherd/examples/rooster.py,sha256=505MzfGM6iqQtffncLOA9Oj5aDeep-_oWS7yEzJbh4o,580
25
- roboherd/examples/scarecrow.py,sha256=o-54QN63LmxfufslmCDvx1ilWQ7KVMsUBtl1tPMbkEs,617
26
- roboherd/herd/__init__.py,sha256=DUvzuyB-JWD-awhNzseoMvluugeD02PZF-hJrGVNtJc,2981
27
- roboherd/herd/builder.py,sha256=MSVPRF0Jsxure9kdyCoYJHQ7nYilGAD0_uQaGQ-rQyE,619
28
- roboherd/herd/processor.py,sha256=NkROTAPs6ZoYW_0TSDnNkAfos4cTnaFgwtW3wOFSgQY,1022
29
- roboherd/herd/scheduler.py,sha256=fkR-74bFZ73DmlJje_dQSytxnFFLV5hCa067mXdwvXs,1266
30
- roboherd/herd/test_herd.py,sha256=sQkzGCWdFveLklhaOJUybtl7odO-QOSDdd-_gan1py8,845
31
- roboherd/herd/test_scheduler.py,sha256=wLisqRMSl734P_rjbqMNH5WTQKepwihgr7ZC32nEj80,424
32
- roboherd/herd/types.py,sha256=_EidQbglm0jpsKX1EsL6U2qm_J5wCPhwUi6Avac22Ow,210
33
- roboherd/herd/manager/__init__.py,sha256=n4QFJXQafHhOJZyDO-mAAWE_hoXcE9vYwFGOPqFOiJM,1409
34
- roboherd/herd/manager/config.py,sha256=qfcED9PfzKzDCWaYHefYj8AImcsOFs5daGpJwUrXlV4,1313
35
- roboherd/herd/manager/test_config.py,sha256=cSf6cqFFr5Hbubuc_tDHyDPbVnsKbRg12WUONn6RxIc,1260
36
- roboherd/herd/manager/test_manager.py,sha256=U6xLOry1K74hd_l8ZtO56v8h1TLNn-UYYfsZJuxuCDA,1031
37
- roboherd-0.1.2.dist-info/METADATA,sha256=cNehEq5m5RHO7ItfG40HFXYyPCn60hNw3cYJBgToz6E,798
38
- roboherd-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
39
- roboherd-0.1.2.dist-info/entry_points.txt,sha256=WebdVUmh8Ot-FupKJY6Du8LuFbmezt9yoy2UICqV3bE,52
40
- roboherd-0.1.2.dist-info/RECORD,,