Sveltish
================
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
`Svelte Stores` are one of the secret weapons of the [Svelte
framework](https://svelte.dev/) (the recently voted [most loved web
framework](https://insights.stackoverflow.com/survey/2021#section-most-loved-dreaded-and-wanted-web-frameworks)).
Stores allow easy [reactive
programming](https://en.wikipedia.org/wiki/Reactive_programming) by
presenting an [Observer
pattern](https://en.wikipedia.org/wiki/Observer_pattern) that is as
simple as necessary, but not simpler.
## Install
``` sh
pip install sveltish
```
## How to use
Sometimes, you’ll have values that need to be accessed by multiple
unrelated objects.
For that, you can use `stores`. It is a very simple implementation
(around 100 lines of code) of the Observer/Observable pattern.
A store is simply an object with a `subscribe` method that allows
interested parties to be notified when its value changes.
#### **Writable Stores**
``` python
from sveltish.stores import writable
```
``` python
count = writable(0)
history = [] # logging for testing
# subscribe returns an unsubscriber
def record(x):
history.append(x)
print(history)
stop = count.subscribe(record)
test_eq(history, [0])
```
[0]
We just created a `count` store. Its value can be accessed via a
`callback` we pass in the `count.subscribe` method:
A **Writable** can be set from the outside. When it happens, all its
subscribers will react.
``` python
def increment(): count.update(lambda x: x + 1)
def decrement(): count.update(lambda x: x - 1)
def reset(): count.set(0)
count.set(3)
increment()
decrement()
decrement()
reset()
count.set(42)
test_eq(history, [0, 3, 4, 3, 2, 0, 42])
```
[0, 3]
[0, 3, 4]
[0, 3, 4, 3]
[0, 3, 4, 3, 2]
[0, 3, 4, 3, 2, 0]
[0, 3, 4, 3, 2, 0, 42]
The `unsubscriber`, in this example the `stop` function, stops the
notifications to the `subscriber`.
``` python
stop()
reset()
count.set(22)
test_eq(history, [0, 3, 4, 3, 2, 0, 42])
count
```
w<0> $int: 22
Notice that you can still change the `store` but there was no print
message this time. There was no observer listening.
<div>
> **Note**
>
> [`Observer`](https://fredguth.github.io/sveltish/signals.html#observer),
> `Subscriber` and
> [`Callback`](https://fredguth.github.io/sveltish/signals.html#callback)
> are used as synomyms here.
</div>
When we subscribe new callbacks, they will be promptly informed of the
current state of the `store`.
``` python
stop = count.subscribe(lambda x: print(f"Count is now {x}"))
stop2 = count.subscribe(lambda x: print(f"double of count is {2*x}"))
```
Count is now 22
double of count is 44
``` python
reset()
```
Count is now 0
double of count is 0
``` python
stop()
stop2()
```
You can create an empty `Writable Store`.
``` python
store = writable()
history = []
unsubscribe = store.subscribe(lambda x: history.append(x))
unsubscribe()
test_eq(history, [None])
```
If you try to unsubscribe twice, it won’t break. It just does nothing
the second time… and in the third time… and…
``` python
unsubscribe(), unsubscribe(), unsubscribe()
```
(None, None, None)
Stores assume mutable objects.
<div>
> **Note**
>
> In Python everythong is an object. Here we are calling an object
> something that is not a primitive (eg. int, bool, etc)
</div>
``` python
class Bunch:
__init__ = lambda self, **kw: setattr(self, '__dict__', kw)
obj = Bunch()
called = 0
store = writable(obj)
def callback(x):
global called
called += 1
stop = store.subscribe(callback)
```
``` python
test_eq(called, 1)
obj.a = 1 #type: ignore
store.set(obj)
test_eq(called, 2)
```
#### **Readable Stores**
However… It is clear that not all stores should be writable by whoever
has a reference to them. Many times you want a single `publisher` of
change in store that is only consumed (`subscribed`) by many other
objects. For those cases, we have readable stores.
<div>
> **Note**
>
> The `Publisher Subscriber (PubSub)` pattern is a variant of the
> `Observable/Observer` pattern.
</div>
``` python
from sveltish.stores import readable
```
A Readable store without a `start` function is a constant value and has
no meaning for us. Therefore, `start` is a required argument.
``` python
try:
c = readable(0) # shoud fail
except Exception as error:
print(error)
test_fail(lambda: readable(0))
```
readable() missing 1 required positional argument: 'start'
``` python
class Publisher:
def __init__(self): self.set = lambda x: None
def set_set(self, set):
self.set = set
return lambda: None
def use_set(self, value): self.set(value)
```
``` python
p = Publisher()
reader = readable(0, p.set_set)
reader
```
r<0> $int: 0
Ths store only starts updating after the first subscriber. Here, the
publisher does not change the store.
``` python
p.use_set(1), reader
```
(None, r<0> $int: 0)
``` python
stop = reader.subscribe(lambda x: print(f"reader is now {x}"))
```
reader is now 0
``` python
p.use_set(2)
```
reader is now 2
``` python
stop()
```
Another example of Readable Store usage:
``` python
from threading import Event, Thread
import time
```
``` python
def start(set): # the start function is the publisher
stopped = Event()
def loop(): # needs to be in a separate thread
while not stopped.wait(1): # in seconds
set(time.localtime())
Thread(target=loop).start()
return stopped.set
```
``` python
now = readable(time.localtime(), start)
now
```
r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=41, tm_wday=2, tm_yday=67, tm_isdst=0)
<div>
> **Note**
>
> The `loop` needs to be in its own thread, otherwise the function would
> never return and we would wait forever.
</div>
While there is no subscriber, the Readable will not be updated.
``` python
now
```
r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=41, tm_wday=2, tm_yday=67, tm_isdst=0)
``` python
OhPleaseStop = now.subscribe(lambda x: print(time.strftime(f"%H:%M:%S", x), end="\r"))
```
22:12:41
``` python
time.sleep(2)
OhPleaseStop()
```
22:12:43
<div>
> **Note**
>
> The Svelte Store api allow you to create a Readable Store without a
> Notifier. See discussion
> [here.](https://github.com/sveltejs/svelte/issues/8300)
</div>
#### **Derived Stores**
A `Derived Store` stores a value based on the value of another store.
``` python
from sveltish.stores import derived
```
For example:
``` python
count = writable(1)
stopCount = count.subscribe(lambda x: print(f"count is {x}"))
double = derived(count, lambda x: x * 2)
stopDouble = double.subscribe(lambda x: print(f"double is {x}"))
test_eq(double.get(), 2*count.get())
```
count is 1
double is 2
``` python
count.set(2)
test_eq(double.get(), 4)
```
count is 2
double is 4
``` python
stopCount(), stopDouble()
```
(None, None)
Building on our previous example, we can create a store that derives the
elapsed time since the original store was started.
``` python
elapsing = None
def calc_elapsed(now):
global elapsing
if not elapsing:
elapsing = now
return time.mktime(now) - time.mktime(elapsing)
```
``` python
now
```
r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=43, tm_wday=2, tm_yday=67, tm_isdst=0)
``` python
elapsed = derived(now, lambda x: calc_elapsed(x))
elapsed
```
r<0> $float: 0.0
``` python
stopElapsed = elapsed.subscribe(lambda x: print(f"Elapsed time of source store: {x} seconds.", end="\r"))
```
Elapsed time of source store: 0.0 seconds.
``` python
time.sleep(1)
stopElapsed()
```
Elapsed time of source store: 2.0 seconds.
Derived stores allow us to transform the value of a store. In RxPy they
are called `operators`. You can build several operators like: `filter`,
`fold`, `map`, `zip`…
Let’s build a custom `filter` operator:
``` python
user = writable({"name": "John", "age": 32})
stopLog = user.subscribe(lambda x: print(f"User: {x}"))
```
User: {'name': 'John', 'age': 32}
``` python
name = derived(user, lambda x: x["name"])
stopName = name.subscribe(lambda x: print(f"Name: {x}"))
```
Name: John
``` python
user.update(lambda x: x | {"age": 45})
```
User: {'name': 'John', 'age': 45}
Updating the age does not trigger the `name subscriber`. Let’s see what
happens when we update the name.
``` python
user.update(lambda x: x | {"name": "Fred"})
```
Name: Fred
User: {'name': 'Fred', 'age': 45}
Only changes to the name of the user triggers the `name` subscriber.
``` python
stopName(), stopLog()
```
(None, None)
Another cool thing about Derived Stores is that you can derive from a
list of stores. Let’s build a `zip` operator.
``` python
a = writable([1,2,3,4])
b = writable([5,6,7,8])
a,b
```
(w<0> $list: [1, 2, 3, 4], w<0> $list: [5, 6, 7, 8])
``` python
zipper = derived([a,b], lambda a,b: list(zip(a,b)))
```
``` python
test_eq(zipper.get(), [(1, 5), (2, 6), (3, 7), (4, 8)])
```
While `zipper` has no subscribers, it keeps the initial value, it is
`stopped`.
``` python
a.set([4,3,2,1])
test_eq(zipper.get(), [(1, 5), (2, 6), (3, 7), (4, 8)])
```
A subscription `starts` zipper and it will start to react to the changes
of the stores.
``` python
u = zipper.subscribe(lambda x: None)
test_eq(zipper.get(), [(4, 5), (3, 6), (2, 7), (1, 8)])
```
``` python
b.set([8,7,6,5])
test_eq(zipper.get(), [(4, 8), (3, 7), (2, 6), (1, 5)])
```
``` python
u()
```
#### Store composition with pipes
``` python
writable(1).pipe(lambda x: x + 1).pipe(lambda x: x * 2)
```
r<0> $int: 4
``` python
writable(1).pipe(lambda x: x+1, lambda x: x*2)
```
r<0> $int: 4
``` python
writable(1) | (lambda x: x+1) | (lambda x: x*2)
```
r<0> $int: 4
``` python
a = writable(1)
u5 = (a
| (lambda x: x*2)
| (lambda x: x*2)
| (lambda x: x*2)).subscribe(lambda x: print(f"u5: {x}"))
```
u5: 8
``` python
a.set(2)
```
u5: 16
``` python
u5()
```
## Missing features
You may have noticed that along the way we had always to subscribe and
then had to remember to unsubscribe when we were done. This is a bit of
a nuisance. Svelte has a compiler that provide some [syntatic
sugar](https://svelte.dev/tutorial/auto-subscriptions) to make this
easier. They call it `auto-subscriptions`.
`Sveltish` does not have `auto-subscriptions` yet. But if you have a
nice idea how to implement it, please let me know.
Raw data
{
"_id": null,
"home_page": "https://github.com/fredguth/sveltish",
"name": "sveltish",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "nbdev jupyter notebook python",
"author": "Fred Guth",
"author_email": "fredguth@fredguth.com",
"download_url": "https://files.pythonhosted.org/packages/be/f6/91bc3b2d4d7d67471de2b5d86aa2ed78fa314e4b3942a11d020972c99c7b/sveltish-1.2.9.tar.gz",
"platform": null,
"description": "Sveltish\n================\n\n<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->\n\n`Svelte Stores` are one of the secret weapons of the [Svelte\nframework](https://svelte.dev/) (the recently voted [most loved web\nframework](https://insights.stackoverflow.com/survey/2021#section-most-loved-dreaded-and-wanted-web-frameworks)).\n\nStores allow easy [reactive\nprogramming](https://en.wikipedia.org/wiki/Reactive_programming) by\npresenting an [Observer\npattern](https://en.wikipedia.org/wiki/Observer_pattern) that is as\nsimple as necessary, but not simpler.\n\n## Install\n\n``` sh\npip install sveltish\n```\n\n## How to use\n\nSometimes, you\u2019ll have values that need to be accessed by multiple\nunrelated objects.\n\nFor that, you can use `stores`. It is a very simple implementation\n(around 100 lines of code) of the Observer/Observable pattern.\n\nA store is simply an object with a `subscribe` method that allows\ninterested parties to be notified when its value changes.\n\n#### **Writable Stores**\n\n``` python\nfrom sveltish.stores import writable\n```\n\n``` python\ncount = writable(0)\nhistory = [] # logging for testing\n# subscribe returns an unsubscriber\ndef record(x): \n history.append(x)\n print(history)\nstop = count.subscribe(record)\n\ntest_eq(history, [0])\n```\n\n [0]\n\nWe just created a `count` store. Its value can be accessed via a\n`callback` we pass in the `count.subscribe` method:\n\nA **Writable** can be set from the outside. When it happens, all its\nsubscribers will react.\n\n``` python\ndef increment(): count.update(lambda x: x + 1)\ndef decrement(): count.update(lambda x: x - 1)\ndef reset(): count.set(0)\n\ncount.set(3)\nincrement()\ndecrement()\ndecrement()\nreset()\ncount.set(42)\n\ntest_eq(history, [0, 3, 4, 3, 2, 0, 42])\n```\n\n [0, 3]\n [0, 3, 4]\n [0, 3, 4, 3]\n [0, 3, 4, 3, 2]\n [0, 3, 4, 3, 2, 0]\n [0, 3, 4, 3, 2, 0, 42]\n\nThe `unsubscriber`, in this example the `stop` function, stops the\nnotifications to the `subscriber`.\n\n``` python\nstop()\nreset()\ncount.set(22)\ntest_eq(history, [0, 3, 4, 3, 2, 0, 42])\ncount\n```\n\n w<0> $int: 22\n\nNotice that you can still change the `store` but there was no print\nmessage this time. There was no observer listening.\n\n<div>\n\n> **Note**\n>\n> [`Observer`](https://fredguth.github.io/sveltish/signals.html#observer),\n> `Subscriber` and\n> [`Callback`](https://fredguth.github.io/sveltish/signals.html#callback)\n> are used as synomyms here.\n\n</div>\n\nWhen we subscribe new callbacks, they will be promptly informed of the\ncurrent state of the `store`.\n\n``` python\nstop = count.subscribe(lambda x: print(f\"Count is now {x}\"))\nstop2 = count.subscribe(lambda x: print(f\"double of count is {2*x}\"))\n```\n\n Count is now 22\n double of count is 44\n\n``` python\nreset()\n```\n\n Count is now 0\n double of count is 0\n\n``` python\nstop()\nstop2()\n```\n\nYou can create an empty `Writable Store`.\n\n``` python\nstore = writable()\nhistory = []\nunsubscribe = store.subscribe(lambda x: history.append(x))\nunsubscribe()\ntest_eq(history, [None])\n```\n\nIf you try to unsubscribe twice, it won\u2019t break. It just does nothing\nthe second time\u2026 and in the third time\u2026 and\u2026\n\n``` python\nunsubscribe(), unsubscribe(), unsubscribe()\n```\n\n (None, None, None)\n\nStores assume mutable objects.\n\n<div>\n\n> **Note**\n>\n> In Python everythong is an object. Here we are calling an object\n> something that is not a primitive (eg. int, bool, etc)\n\n</div>\n\n``` python\nclass Bunch:\n __init__ = lambda self, **kw: setattr(self, '__dict__', kw)\n\nobj = Bunch()\ncalled = 0\nstore = writable(obj)\ndef callback(x):\n global called\n called += 1\nstop = store.subscribe(callback)\n```\n\n``` python\ntest_eq(called, 1)\nobj.a = 1 #type: ignore\nstore.set(obj)\ntest_eq(called, 2)\n```\n\n#### **Readable Stores**\n\nHowever\u2026 It is clear that not all stores should be writable by whoever\nhas a reference to them. Many times you want a single `publisher` of\nchange in store that is only consumed (`subscribed`) by many other\nobjects. For those cases, we have readable stores.\n\n<div>\n\n> **Note**\n>\n> The `Publisher Subscriber (PubSub)` pattern is a variant of the\n> `Observable/Observer` pattern.\n\n</div>\n\n``` python\nfrom sveltish.stores import readable\n```\n\nA Readable store without a `start` function is a constant value and has\nno meaning for us. Therefore, `start` is a required argument.\n\n``` python\ntry:\n c = readable(0) # shoud fail\nexcept Exception as error:\n print(error)\n\ntest_fail(lambda: readable(0))\n```\n\n readable() missing 1 required positional argument: 'start'\n\n``` python\nclass Publisher:\n def __init__(self): self.set = lambda x: None\n def set_set(self, set): \n self.set = set\n return lambda: None\n def use_set(self, value): self.set(value)\n```\n\n``` python\np = Publisher()\nreader = readable(0, p.set_set)\nreader\n```\n\n r<0> $int: 0\n\nThs store only starts updating after the first subscriber. Here, the\npublisher does not change the store.\n\n``` python\np.use_set(1), reader\n```\n\n (None, r<0> $int: 0)\n\n``` python\nstop = reader.subscribe(lambda x: print(f\"reader is now {x}\"))\n```\n\n reader is now 0\n\n``` python\np.use_set(2)\n```\n\n reader is now 2\n\n``` python\nstop()\n```\n\nAnother example of Readable Store usage:\n\n``` python\nfrom threading import Event, Thread\nimport time\n```\n\n``` python\ndef start(set): # the start function is the publisher\n stopped = Event()\n def loop(): # needs to be in a separate thread\n while not stopped.wait(1): # in seconds\n set(time.localtime())\n Thread(target=loop).start() \n return stopped.set\n```\n\n``` python\nnow = readable(time.localtime(), start)\nnow\n```\n\n r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=41, tm_wday=2, tm_yday=67, tm_isdst=0)\n\n<div>\n\n> **Note**\n>\n> The `loop` needs to be in its own thread, otherwise the function would\n> never return and we would wait forever.\n\n</div>\n\nWhile there is no subscriber, the Readable will not be updated.\n\n``` python\nnow\n```\n\n r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=41, tm_wday=2, tm_yday=67, tm_isdst=0)\n\n``` python\nOhPleaseStop = now.subscribe(lambda x: print(time.strftime(f\"%H:%M:%S\", x), end=\"\\r\"))\n```\n\n 22:12:41\n\n``` python\ntime.sleep(2)\nOhPleaseStop()\n```\n\n 22:12:43\n\n<div>\n\n> **Note**\n>\n> The Svelte Store api allow you to create a Readable Store without a\n> Notifier. See discussion\n> [here.](https://github.com/sveltejs/svelte/issues/8300)\n\n</div>\n\n#### **Derived Stores**\n\nA `Derived Store` stores a value based on the value of another store.\n\n``` python\nfrom sveltish.stores import derived\n```\n\nFor example:\n\n``` python\ncount = writable(1)\nstopCount = count.subscribe(lambda x: print(f\"count is {x}\"))\ndouble = derived(count, lambda x: x * 2)\nstopDouble = double.subscribe(lambda x: print(f\"double is {x}\"))\ntest_eq(double.get(), 2*count.get())\n```\n\n count is 1\n double is 2\n\n``` python\ncount.set(2)\ntest_eq(double.get(), 4)\n```\n\n count is 2\n double is 4\n\n``` python\nstopCount(), stopDouble()\n```\n\n (None, None)\n\nBuilding on our previous example, we can create a store that derives the\nelapsed time since the original store was started.\n\n``` python\nelapsing = None\ndef calc_elapsed(now):\n global elapsing\n if not elapsing: \n elapsing = now\n return time.mktime(now) - time.mktime(elapsing)\n```\n\n``` python\nnow\n```\n\n r<0> $struct_time: time.struct_time(tm_year=2023, tm_mon=3, tm_mday=8, tm_hour=22, tm_min=12, tm_sec=43, tm_wday=2, tm_yday=67, tm_isdst=0)\n\n``` python\nelapsed = derived(now, lambda x: calc_elapsed(x))\nelapsed\n```\n\n r<0> $float: 0.0\n\n``` python\nstopElapsed = elapsed.subscribe(lambda x: print(f\"Elapsed time of source store: {x} seconds.\", end=\"\\r\"))\n```\n\n Elapsed time of source store: 0.0 seconds.\n\n``` python\ntime.sleep(1)\nstopElapsed()\n```\n\n Elapsed time of source store: 2.0 seconds.\n\nDerived stores allow us to transform the value of a store. In RxPy they\nare called `operators`. You can build several operators like: `filter`,\n`fold`, `map`, `zip`\u2026\n\nLet\u2019s build a custom `filter` operator:\n\n``` python\nuser = writable({\"name\": \"John\", \"age\": 32})\nstopLog = user.subscribe(lambda x: print(f\"User: {x}\"))\n```\n\n User: {'name': 'John', 'age': 32}\n\n``` python\nname = derived(user, lambda x: x[\"name\"])\nstopName = name.subscribe(lambda x: print(f\"Name: {x}\"))\n```\n\n Name: John\n\n``` python\nuser.update(lambda x: x | {\"age\": 45})\n```\n\n User: {'name': 'John', 'age': 45}\n\nUpdating the age does not trigger the `name subscriber`. Let\u2019s see what\nhappens when we update the name.\n\n``` python\nuser.update(lambda x: x | {\"name\": \"Fred\"})\n```\n\n Name: Fred\n User: {'name': 'Fred', 'age': 45}\n\nOnly changes to the name of the user triggers the `name` subscriber.\n\n``` python\nstopName(), stopLog()\n```\n\n (None, None)\n\nAnother cool thing about Derived Stores is that you can derive from a\nlist of stores. Let\u2019s build a `zip` operator.\n\n``` python\na = writable([1,2,3,4])\nb = writable([5,6,7,8])\na,b\n```\n\n (w<0> $list: [1, 2, 3, 4], w<0> $list: [5, 6, 7, 8])\n\n``` python\nzipper = derived([a,b], lambda a,b: list(zip(a,b)))\n```\n\n``` python\ntest_eq(zipper.get(), [(1, 5), (2, 6), (3, 7), (4, 8)])\n```\n\nWhile `zipper` has no subscribers, it keeps the initial value, it is\n`stopped`.\n\n``` python\na.set([4,3,2,1])\ntest_eq(zipper.get(), [(1, 5), (2, 6), (3, 7), (4, 8)])\n```\n\nA subscription `starts` zipper and it will start to react to the changes\nof the stores.\n\n``` python\nu = zipper.subscribe(lambda x: None)\ntest_eq(zipper.get(), [(4, 5), (3, 6), (2, 7), (1, 8)])\n```\n\n``` python\nb.set([8,7,6,5])\ntest_eq(zipper.get(), [(4, 8), (3, 7), (2, 6), (1, 5)])\n```\n\n``` python\nu()\n```\n\n#### Store composition with pipes\n\n``` python\nwritable(1).pipe(lambda x: x + 1).pipe(lambda x: x * 2)\n```\n\n r<0> $int: 4\n\n``` python\nwritable(1).pipe(lambda x: x+1, lambda x: x*2)\n```\n\n r<0> $int: 4\n\n``` python\nwritable(1) | (lambda x: x+1) | (lambda x: x*2)\n```\n\n r<0> $int: 4\n\n``` python\na = writable(1)\nu5 = (a \n | (lambda x: x*2) \n | (lambda x: x*2) \n | (lambda x: x*2)).subscribe(lambda x: print(f\"u5: {x}\"))\n```\n\n u5: 8\n\n``` python\na.set(2)\n```\n\n u5: 16\n\n``` python\nu5()\n```\n\n## Missing features\n\nYou may have noticed that along the way we had always to subscribe and\nthen had to remember to unsubscribe when we were done. This is a bit of\na nuisance. Svelte has a compiler that provide some [syntatic\nsugar](https://svelte.dev/tutorial/auto-subscriptions) to make this\neasier. They call it `auto-subscriptions`.\n\n`Sveltish` does not have `auto-subscriptions` yet. But if you have a\nnice idea how to implement it, please let me know.\n",
"bugtrack_url": null,
"license": "Apache Software License 2.0",
"summary": "A Svelte Stores implementation in Python.",
"version": "1.2.9",
"split_keywords": [
"nbdev",
"jupyter",
"notebook",
"python"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "37391a56e57b4e77c3d700b2e2b81b7d75e6ff8d7c9a987dc72f6e9b1c52feda",
"md5": "ac7532e9d90d62367bc2d4f422960a95",
"sha256": "12f9f02cec4d7c59415bff98b93aa2514aa5a82fef126a975a3743de668c48b3"
},
"downloads": -1,
"filename": "sveltish-1.2.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ac7532e9d90d62367bc2d4f422960a95",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 16054,
"upload_time": "2023-03-15T18:53:58",
"upload_time_iso_8601": "2023-03-15T18:53:58.298654Z",
"url": "https://files.pythonhosted.org/packages/37/39/1a56e57b4e77c3d700b2e2b81b7d75e6ff8d7c9a987dc72f6e9b1c52feda/sveltish-1.2.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "bef691bc3b2d4d7d67471de2b5d86aa2ed78fa314e4b3942a11d020972c99c7b",
"md5": "0f9986c9b4eb698141d17df37ec800e4",
"sha256": "08e408471dbd5365c9a9573307d33cf889cd84480cbf869b2479c554c1ebae97"
},
"downloads": -1,
"filename": "sveltish-1.2.9.tar.gz",
"has_sig": false,
"md5_digest": "0f9986c9b4eb698141d17df37ec800e4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 19573,
"upload_time": "2023-03-15T18:54:01",
"upload_time_iso_8601": "2023-03-15T18:54:01.067465Z",
"url": "https://files.pythonhosted.org/packages/be/f6/91bc3b2d4d7d67471de2b5d86aa2ed78fa314e4b3942a11d020972c99c7b/sveltish-1.2.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-03-15 18:54:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "fredguth",
"github_project": "sveltish",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sveltish"
}