2012-03-23 15:48:43 -07:00
|
|
|
import hashlib
|
2023-11-02 04:52:30 -07:00
|
|
|
import pickle
|
2023-02-15 11:57:09 -08:00
|
|
|
import re
|
2019-02-18 11:14:56 -08:00
|
|
|
|
2014-12-08 17:52:55 -08:00
|
|
|
import markdown
|
2010-10-07 17:45:09 -07:00
|
|
|
from django.core.cache import cache
|
2012-07-07 15:28:02 -07:00
|
|
|
from django.db import connections, router
|
2013-04-16 19:59:32 -07:00
|
|
|
from django.http import HttpResponse
|
2012-12-28 08:12:09 -08:00
|
|
|
from django.template.defaultfilters import slugify
|
2023-11-02 04:52:30 -07:00
|
|
|
from django.utils.timezone import now
|
|
|
|
from markdown.extensions import Extension
|
|
|
|
from pgpdump.packet import SignaturePacket
|
2010-06-20 22:50:13 -07:00
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2010-10-13 15:55:28 -07:00
|
|
|
def cache_function_key(func, args, kwargs):
|
|
|
|
raw = [func.__name__, func.__module__, args, kwargs]
|
|
|
|
pickled = pickle.dumps(raw, protocol=pickle.HIGHEST_PROTOCOL)
|
2012-03-23 15:48:43 -07:00
|
|
|
key = hashlib.md5(pickled).hexdigest()
|
2010-10-13 15:55:28 -07:00
|
|
|
return 'cache_function.' + func.__name__ + '.' + key
|
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2010-06-20 22:50:13 -07:00
|
|
|
def cache_function(length):
|
|
|
|
"""
|
|
|
|
A variant of the snippet posted by Jeff Wheeler at
|
|
|
|
http://www.djangosnippets.org/snippets/109/
|
|
|
|
|
|
|
|
Caches a function, using the function and its arguments as the key, and the
|
|
|
|
return value as the value saved. It passes all arguments on to the
|
|
|
|
function, as it should.
|
|
|
|
|
|
|
|
The decorator itself takes a length argument, which is the number of
|
|
|
|
seconds the cache will keep the result around.
|
|
|
|
"""
|
|
|
|
def decorator(func):
|
|
|
|
def inner_func(*args, **kwargs):
|
2010-10-13 15:55:28 -07:00
|
|
|
key = cache_function_key(func, args, kwargs)
|
2010-06-20 22:50:13 -07:00
|
|
|
value = cache.get(key)
|
|
|
|
if value is not None:
|
|
|
|
return value
|
|
|
|
else:
|
|
|
|
result = func(*args, **kwargs)
|
|
|
|
cache.set(key, result, length)
|
|
|
|
return result
|
|
|
|
return inner_func
|
|
|
|
return decorator
|
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2010-10-13 15:55:28 -07:00
|
|
|
def clear_cache_function(func, args, kwargs):
|
|
|
|
key = cache_function_key(func, args, kwargs)
|
|
|
|
cache.delete(key)
|
|
|
|
|
2012-09-04 06:53:39 -07:00
|
|
|
|
2013-04-16 19:59:32 -07:00
|
|
|
def empty_response():
|
|
|
|
empty = HttpResponse('')
|
|
|
|
# designating response as 'streaming' forces ConditionalGetMiddleware to
|
|
|
|
# not add a 'Content-Length: 0' header
|
|
|
|
empty.streaming = True
|
|
|
|
return empty
|
|
|
|
|
|
|
|
|
2010-10-13 16:11:28 -07:00
|
|
|
# utility to make a pair of django choices
|
2023-05-19 04:45:41 -07:00
|
|
|
make_choice = lambda l: [(str(m), str(m)) for m in l] # noqa E741
|
2010-10-13 15:55:28 -07:00
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2011-06-29 08:52:30 -07:00
|
|
|
def set_created_field(sender, **kwargs):
|
2012-03-23 17:29:40 -07:00
|
|
|
'''This will set the 'created' field on any object to the current UTC time
|
2012-12-27 19:13:56 -08:00
|
|
|
if it is unset.
|
|
|
|
Additionally, this will set the 'last_modified' field on any object to the
|
|
|
|
current UTC time on any save of the object.
|
|
|
|
For use as a pre_save signal handler.'''
|
2011-06-29 08:52:30 -07:00
|
|
|
obj = kwargs['instance']
|
2012-12-27 19:13:56 -08:00
|
|
|
time = now()
|
2011-06-29 08:52:30 -07:00
|
|
|
if hasattr(obj, 'created') and not obj.created:
|
2012-12-27 19:13:56 -08:00
|
|
|
obj.created = time
|
|
|
|
if hasattr(obj, 'last_modified'):
|
|
|
|
obj.last_modified = time
|
2011-06-29 08:52:30 -07:00
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2012-12-28 08:12:09 -08:00
|
|
|
def find_unique_slug(model, title):
|
|
|
|
'''Attempt to find a unique slug for this model with given title.'''
|
|
|
|
existing = set(model.objects.values_list(
|
|
|
|
'slug', flat=True).order_by().distinct())
|
|
|
|
|
|
|
|
suffixed = slug = slugify(title)
|
|
|
|
suffix = 0
|
|
|
|
while suffixed in existing:
|
|
|
|
suffix += 1
|
|
|
|
suffixed = "%s-%d" % (slug, suffix)
|
|
|
|
|
|
|
|
return suffixed
|
|
|
|
|
|
|
|
|
2012-07-07 15:28:02 -07:00
|
|
|
def database_vendor(model, mode='read'):
|
|
|
|
if mode == 'read':
|
|
|
|
database = router.db_for_read(model)
|
|
|
|
elif mode == 'write':
|
|
|
|
database = router.db_for_write(model)
|
|
|
|
else:
|
|
|
|
raise Exception('Invalid database mode specified')
|
|
|
|
return connections[database].vendor
|
|
|
|
|
|
|
|
|
2014-12-08 17:52:55 -08:00
|
|
|
class EscapeHtml(Extension):
|
2021-10-31 09:51:08 -07:00
|
|
|
def extendMarkdown(self, md):
|
|
|
|
md.preprocessors.deregister('html_block')
|
|
|
|
md.inlinePatterns.deregister('html')
|
2014-12-08 17:52:55 -08:00
|
|
|
|
|
|
|
|
|
|
|
def parse_markdown(text, allow_html=False):
|
|
|
|
if allow_html:
|
2021-10-31 09:52:07 -07:00
|
|
|
return markdown.markdown(text)
|
2014-12-08 17:52:55 -08:00
|
|
|
ext = [EscapeHtml()]
|
2021-10-31 09:52:07 -07:00
|
|
|
return markdown.markdown(text, extensions=ext)
|
2014-12-08 17:52:55 -08:00
|
|
|
|
|
|
|
|
2011-06-29 10:05:07 -07:00
|
|
|
def groupby_preserve_order(iterable, keyfunc):
|
|
|
|
'''Take an iterable and regroup using keyfunc to determine whether items
|
|
|
|
belong to the same group. The order of the iterable is preserved and
|
|
|
|
similar keys do not have to be consecutive. This means the earliest
|
|
|
|
occurrence of a given key will determine the order of the lists in the
|
|
|
|
returned list.'''
|
|
|
|
seen_keys = {}
|
|
|
|
result = []
|
|
|
|
for item in iterable:
|
|
|
|
key = keyfunc(item)
|
|
|
|
|
|
|
|
group = seen_keys.get(key, None)
|
|
|
|
if group is None:
|
|
|
|
group = []
|
|
|
|
seen_keys[key] = group
|
|
|
|
result.append(group)
|
|
|
|
|
|
|
|
group.append(item)
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
2012-03-23 16:45:01 -07:00
|
|
|
|
2023-02-15 11:57:09 -08:00
|
|
|
def gitlab_project_name_to_path(name: str) -> str:
|
|
|
|
'''Convert a Gitlab project name to variant which the Gitlab encodes in
|
|
|
|
its url / API for example mysql++ becomes mysqlplusplus.'''
|
|
|
|
|
|
|
|
name = re.sub(r'([a-zA-Z0-9]+)\+([a-zA-Z]+)', r'\1-\2', name)
|
|
|
|
name = re.sub(r'\+', r'plus', name)
|
|
|
|
name = re.sub(r'[^a-zA-Z0-9_\-\.]', r'-', name)
|
|
|
|
name = re.sub(r'[_\-]{2,}', r'-', name)
|
|
|
|
name = re.sub(r'^tree$', r'unix-tree', name)
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
2011-06-29 10:05:07 -07:00
|
|
|
class PackageStandin(object):
|
|
|
|
'''Resembles a Package object, and has a few of the same fields, but is
|
|
|
|
really a link to a pkgbase that has no package with matching pkgname.'''
|
2021-10-31 09:51:08 -07:00
|
|
|
|
2011-06-29 10:05:07 -07:00
|
|
|
def __init__(self, package):
|
|
|
|
self.package = package
|
|
|
|
self.pkgname = package.pkgbase
|
|
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
|
return getattr(self.package, name)
|
|
|
|
|
|
|
|
def get_absolute_url(self):
|
2020-10-03 21:59:41 -07:00
|
|
|
return f'/packages/{self.repo.name.lower()}/{self.arch.name}/{self.pkgname}/'
|
2011-06-29 10:05:07 -07:00
|
|
|
|
2013-11-11 14:28:34 -08:00
|
|
|
|
|
|
|
class DependStandin(object):
|
|
|
|
'''Resembles a Depend object, and has a few of the same fields, but is
|
|
|
|
really a link to a base package rather than a single package.'''
|
2021-10-31 09:51:08 -07:00
|
|
|
|
2013-11-11 14:28:34 -08:00
|
|
|
def __init__(self, depends):
|
|
|
|
self._depends = depends
|
|
|
|
first = depends[0]
|
|
|
|
self.name = first.name
|
|
|
|
self.version = first.version
|
|
|
|
self.comparison = first.comparison
|
|
|
|
self.description = first.description
|
|
|
|
self.deptype = first.deptype
|
|
|
|
self.pkg = first.pkg.base_package() or PackageStandin(first.pkg)
|
|
|
|
|
2019-02-08 09:49:15 -08:00
|
|
|
|
|
|
|
class SignatureWrapper(SignaturePacket):
|
|
|
|
'Decode key_id from raw SignaturePacket'
|
2021-10-31 09:51:08 -07:00
|
|
|
|
2019-02-08 09:49:15 -08:00
|
|
|
def __init__(self, packet):
|
|
|
|
for field in ("sig_version", "creation_time", "expiration_time"):
|
|
|
|
setattr(self, field, getattr(packet, field))
|
2019-02-08 10:02:09 -08:00
|
|
|
self.key_id = packet.key_id.decode() if packet.key_id else None
|
2019-02-08 09:49:15 -08:00
|
|
|
|
2010-10-13 15:55:28 -07:00
|
|
|
# vim: set ts=4 sw=4 et:
|