alfred-async 0.1.0__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.
@@ -0,0 +1,132 @@
1
+ import abc
2
+ import asyncio
3
+ import hashlib
4
+ import json
5
+ import logging
6
+ import pathlib
7
+ import plistlib
8
+ from datetime import UTC, datetime, timedelta
9
+ from functools import wraps
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def hash(string):
15
+ h = hashlib.new("sha256")
16
+ h.update(string.encode())
17
+ return h.hexdigest()
18
+
19
+
20
+ class Path(pathlib.Path):
21
+ def mtime(self) -> datetime:
22
+ return datetime.fromtimestamp(self.stat().st_mtime, tz=UTC)
23
+
24
+ def age(self) -> timedelta:
25
+ return datetime.now(UTC) - self.mtime()
26
+
27
+
28
+ def cache_json(f):
29
+ @wraps(f)
30
+ async def wrapper(client: "WorkflowClient", *args, **kwds):
31
+ key = hash(str(kwds))
32
+ path = Path(client.cache_directory / key).with_suffix(".json")
33
+ if client.is_cached(path):
34
+ logger.debug("Reading data for %s", path)
35
+ with path.open() as fp:
36
+ return json.load(fp)
37
+ data = await f(client, *args, **kwds)
38
+ logger.info("Writing data for %s", path)
39
+ if not client.cache_directory.exists():
40
+ client.cache_directory.mkdir(parents=True)
41
+ with path.open("w") as fp:
42
+ json.dump(data, fp, indent=True)
43
+ return data
44
+
45
+ return wrapper
46
+
47
+
48
+ def cache_path(f):
49
+ @wraps(f)
50
+ async def wrapper(client: "WorkflowClient", *args, **kwds):
51
+ key = hash(str(kwds))
52
+ path = Path(client.cache_directory / key)
53
+ if client.is_cached(path):
54
+ logger.debug("Reading data for %s", path)
55
+ return path
56
+ data = await f(client, *args, **kwds)
57
+ logger.info("Writing data for %s", path)
58
+ if not client.cache_directory.exists():
59
+ client.cache_directory.mkdir(parents=True)
60
+ with path.open("wb+") as fp:
61
+ fp.write(data)
62
+ return path
63
+
64
+ return wrapper
65
+
66
+
67
+ class JsonPathEncoder(json.JSONEncoder):
68
+ def default(self, o):
69
+ if isinstance(o, Path):
70
+ return str(o)
71
+ return super().default(o)
72
+
73
+
74
+ class WorkflowClient:
75
+ def __init__(self):
76
+ self.plist_path = Path.cwd() / "info.plist"
77
+ if self.plist_path.exists():
78
+ with self.plist_path.open("rb") as fp:
79
+ self.plist = plistlib.load(fp)
80
+ self.bundleid = self.plist["bundleid"]
81
+
82
+ @property
83
+ def alfred_preferences(self) -> Path:
84
+ return (
85
+ Path.home()
86
+ / "Library"
87
+ / "Application Support"
88
+ / "Alfred"
89
+ / "Alfred.preferences"
90
+ / self.bundleid
91
+ )
92
+
93
+ @property
94
+ def cache_directory(self) -> Path:
95
+ return (
96
+ Path.home()
97
+ / "Caches"
98
+ / "com.runningwithcrayons.Alfred"
99
+ / "Workflow Data"
100
+ / self.bundleid
101
+ )
102
+
103
+ def is_cached(self, path: Path, duration=timedelta(minutes=5)):
104
+ if path.exists():
105
+ if path.age() < duration:
106
+ return True
107
+ return False
108
+
109
+ results = []
110
+
111
+ async def add_result(self, icon_path: str = None, **kwargs):
112
+ if icon_path and icon_path.startswith("http"):
113
+ logger.debug("need to download %s", icon_path)
114
+ kwargs["icon_path"] = await self.icon(icon_path)
115
+ self.results.append(kwargs)
116
+
117
+ async def loop(self):
118
+ try:
119
+ await self.run()
120
+ except Exception:
121
+ logger.exception("Error with workflow")
122
+ else:
123
+ print(json.dumps({"items": self.results}, cls=JsonPathEncoder))
124
+
125
+ @abc.abstractmethod
126
+ async def run(self):
127
+ raise NotImplementedError()
128
+
129
+ @classmethod
130
+ def main(cls):
131
+ client = cls()
132
+ return asyncio.run(client.loop())
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: alfred-async
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Requires-Python: >=3.12
6
+ Description-Content-Type: text/markdown
@@ -0,0 +1,5 @@
1
+ alfred_async/__init__.py,sha256=kuMv1U6cwovX0VaqzHSC9OuLiyVTM8pG3KhnORFBcWY,3639
2
+ alfred_async-0.1.0.dist-info/METADATA,sha256=gXogOzcV_kXkAuUst2_tDPLNW33JYBzr1zAZp7BeALE,155
3
+ alfred_async-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
4
+ alfred_async-0.1.0.dist-info/top_level.txt,sha256=GzxgSiSAemnPvhoEN3fSLMNtdTf3YSgR0PxITPG61cs,13
5
+ alfred_async-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ alfred_async