Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sametmax/Bat-belt
A collection of gagdets make Python even more powerful
https://github.com/sametmax/Bat-belt
Last synced: 3 months ago
JSON representation
A collection of gagdets make Python even more powerful
- Host: GitHub
- URL: https://github.com/sametmax/Bat-belt
- Owner: sametmax
- Created: 2012-10-14T22:55:42.000Z (about 12 years ago)
- Default Branch: master
- Last Pushed: 2017-09-30T10:10:16.000Z (about 7 years ago)
- Last Synced: 2024-08-18T16:43:41.097Z (4 months ago)
- Language: Python
- Size: 230 KB
- Stars: 33
- Watchers: 9
- Forks: 6
- Open Issues: 1
-
Metadata Files:
- Readme: README.rst
Awesome Lists containing this project
README
*************************************************************
A collection of gagdets that makes Python even more powerful
*************************************************************There is not real structure for this lib, it's just a bunch of snippets I put together because I use them often.
Not all of them are documented here, few of them have tests, it's zlib licence, you know the drill...
To timestamp
=============
datetime.fromtimestamp
exists but not the other away around, and it's not likely to change anytime soon (see: http://bugs.python.org/issue2736). In the meantime::>>> from datetime import datetime
>>> to_timestamp(datetime(2000, 1, 1, 2, 1, 1))
946692061
>>> datetime.fromtimestamp(946688461) # tu as codé celle là et pas l'autre connard !
datetime.datetime(2000, 1, 1, 2, 1, 1)Get this nest value or a default
=================================Don't::
try:
res = data['key'][0]['other key'][1]
except (KeyError, IndexError):
res = "value"Do::
get(data, 'key', 0, 'other key, 1, default="value")
For attributes::
devise = attr(car, 'insurance', 'expiration_date', 'timezone')
Iteration tools missing in itertools
===================================================================================Iteration by chunk or with a sliding window::
>>> for chunk in chunks(l, 3):
... print list(chunk)
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
>>> for slide in window(l, 3):
... print list(slide)
...
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]Get the first element an any iterable (not just indexable) or the first one to be True::
>>> first(xrange(10))
0
>>> first_true(xrange(10))
1
>>> first([], default="What the one thing we say to the God of Death ?")
'What the one thing we say to the God of Death ?'Sorted Set
===================================================================================Slow but useful data structure::
>>> for x in sset((3, 2, 2, 2, 1, 2)):
... print x
...
3
2
1Dictionaries one liners
===================================================================================I wish
+
was overloaded for dicts::>>> dmerge({"a": 1, "b": 2}, {"b": 2, "c": 3})
{'a': 1, 'c': 3, 'b': 2}Sometimes you do not want to simply overwrite the values inside the original dict, but merge them in custom fashion::
>>> def my_merge(v1, v2):
... if isinstance(v1, dict) and isinstance(v2, dict):
... return dmerge(v1, v2)
... return v2
>>> dmerge({"a": 1, "b": {'ok': 5}}, {"b": {'ko': 5 }, "c": 3}, my_merge)
{'a': 1, 'c': 3, 'b': {'ko': 5, 'ok': 5}}Original dicts are not modified, but this will modify them::
>>> from batbelt.structs import rename
>>> rename({"a": 1, "b": 2})
>>> rename({"a": 1, "b": 2}, 'b', 'z')
{u'a': 1, u'z': 2}(not thread safe).
Twited but satisfying::
>>> from batbelt.structs import unpack
>>> dct = {'a': 2, 'b': 4, 'z': 42}
>>> a, b, c = unpack(dct, 'a', 'b', 'c', default=1)
>>> a
2
>>> b
4
>>> c
1String tools
===================================================================================The mandatory "slufigy"::
>>> slugify(u"Hélo Whorde")
helo-whordeYou get better slugification if you install the `unidecode` lib, but it's optional. You can specify `separator` if you don't like `-` or call directly `normalize()` (the underlying function) if you wish more control.
The module also feature html_escape/unescape that is not useless and json_dumps/loads that understand datetime by default. Look at the source for these, I'm lazy (PL for documentation are welcome).
There is also a poor man template system using the `format()` string method on a file content. No loop, but still nice for quick and dirty file generation :
from batbelt.strings import render
render('stuff.conf.tpl', {"var": "value"}, "/etc/stuff.conf")
Import this
===================================================================================`__import__` is weird. Let's abstract that ::
TaClasse = import_from_path('foo.bar.TaClasse')
ton_obj = TaClasse()Catpure prints
===================================================================================A context manager to deal with this libs that print the result instead of returning it :
>>> with capture_ouput() as (stdout, stderr):
... print "hello",
...
>>> print stdout.read()
hello
>>> stdout.close()Create a decorator that accept arguments
===================================================================================I never remember how to do this. And I don't have to anymore.
First, write the decorator::
# all arguments after 'func' are your decorator argument
@decorator_with_args()
def your_decorator(func, arg1, arg2=None):if arg1:
# do stuff here# do your usual decorator jimbo jumbo, wrapping, calling, returning...
def wrapper():
return func(arg2)return wrapper
Enjoy :
@your_decorator(False, 1)
def hop(un_arg):
# do stuff in the decorated functionAdd a any directory to the PYTHON PATH
===========================================Accepts shell variables and relative paths :
from batbelt.utils import add_to_pythonpath
add_to_pythonpath("~/..")You can (and probably wants) specify a starting point if you pass a relative path. The default starting point is the result is `os.getcwd()` while you probably wants the directory containing you script. To to so, pass `__file__`:
add_to_pythonpath("../..", starting_point=__file__)
`starting_point` can be a file path (basename will be stripped) or a directory name. If will be from there that the reltive path will be calculated.
You can also choose where in the `sys.path` list the your path will be added by passing `insertion_index`, which default to the after the last existing item.
Poor man task queue
===================================================================================================You don't always need the guaranty of a big lib, you just need a little worker to do the job outside of the main thread::
from batbelt.parallel import worker
@worker()
def task(arg):
arg = arg + 10
return arg# start the worker
process = task.start()# send tasks
for x in range(10):
process.put(x)# (optionaly) get results
for x in range(10):
print process.get()## 10
## 11
## 12
## 13
## 14
## 15
## 16
## 17
## 18
## 19# stop the worker
process.stop()The worker use multiprocessing by default, but if you prefer threads: `@worker(method="tread")`.
If you look for it in the source code, you'll see goodies such as Singletong, Null Pattern implementation and other things you don't use that often.