Utilities

These functions are not dependent on Flask. They implement common patterns in Flask-based applications.

class coaster.utils.LabeledEnum[source]

Labeled enumerations. Declarate an enumeration with values and labels (for use in UI):

>>> class MY_ENUM(LabeledEnum):
...    FIRST = (1, "First")
...    THIRD = (3, "Third")
...    SECOND = (2, "Second")

LabeledEnum will convert any attribute that is a 2-tuple into a value and label pair. Access values as direct attributes of the enumeration:

>>> MY_ENUM.FIRST
1
>>> MY_ENUM.SECOND
2
>>> MY_ENUM.THIRD
3

Access labels via dictionary lookup on the enumeration:

>>> MY_ENUM[MY_ENUM.FIRST]
'First'
>>> MY_ENUM[2]
'Second'
>>> MY_ENUM.get(3)
'Third'
>>> MY_ENUM.get(4) is None
True

Retrieve a full list of values and labels with .items(). Items are always sorted by value regardless of the original definition order (since Python doesn’t provide a way to preserve that order):

>>> MY_ENUM.items()
[(1, 'First'), (2, 'Second'), (3, 'Third')]

Three value tuples are assumed to be (value, name, title) and the name and title are converted into NameTitle(name, title):

>>> class NAME_ENUM(LabeledEnum):
...    FIRST = (1, 'first', "First")
...    THIRD = (3, 'third', "Third")
...    SECOND = (2, 'second', "Second")

>>> NAME_ENUM.FIRST
1
>>> NAME_ENUM[NAME_ENUM.FIRST]
NameTitle(name='first', title='First')
>>> NAME_ENUM[NAME_ENUM.SECOND].name
'second'
>>> NAME_ENUM[NAME_ENUM.THIRD].title
'Third'

Given a name, the value can be looked up:

>>> NAME_ENUM.value_for('first')
1
>>> NAME_ENUM.value_for('second')
2
class coaster.utils.NameTitle

NameTitle(name, title)

name

Alias for field number 0

title

Alias for field number 1

coaster.utils.base_domain_matches(d1, d2)[source]

Check if two domains have the same base domain, using the Public Suffix List.

>>> base_domain_matches('https://hasjob.co', 'hasjob.co')
True
>>> base_domain_matches('hasgeek.hasjob.co', 'hasjob.co')
True
>>> base_domain_matches('hasgeek.com', 'hasjob.co')
False
>>> base_domain_matches('static.hasgeek.co.in', 'hasgeek.com')
False
>>> base_domain_matches('static.hasgeek.co.in', 'hasgeek.co.in')
True
>>> base_domain_matches('example@example.com', 'example.com')
True
coaster.utils.buid()[source]

Return a new random id that is exactly 22 characters long, by encoding a UUID4 in URL-safe Base64. See http://en.wikipedia.org/wiki/Base64#Variants_summary_table

>>> len(newid())
22
>>> newid() == newid()
False
>>> isinstance(newid(), unicode)
True
coaster.utils.check_password(reference, attempt)[source]

Compare a reference password with the user attempt.

>>> check_password('{PLAIN}foo', 'foo')
True
>>> check_password(u'{PLAIN}bar', 'bar')
True
>>> check_password(u'{UNKNOWN}baz', 'baz')
False
>>> check_password(u'no-encoding', u'no-encoding')
False
>>> check_password(u'{SSHA}q/uVU8r15k/9QhRi92CWUwMJu2DM6TUSpp25', u're-foo')
True
>>> check_password('{SSHA}q/uVU8r15k/9QhRi92CWUwMJu2DM6TUSpp25', 're-foo')
True
coaster.utils.deobfuscate_email(text)[source]

Deobfuscate email addresses in provided text

coaster.utils.domain_namespace_match(domain, namespace)[source]

Checks if namespace is related to the domain because the base domain matches.

>>> domain_namespace_match('hasgeek.com', 'com.hasgeek')
True
>>> domain_namespace_match('funnel.hasgeek.com', 'com.hasgeek.funnel')
True
>>> domain_namespace_match('app.hasgeek.com', 'com.hasgeek.peopleflow')
True
>>> domain_namespace_match('app.hasgeek.in', 'com.hasgeek.peopleflow')
False
>>> domain_namespace_match('peopleflow.local', 'local.peopleflow')
True
coaster.utils.format_currency(value, decimals=2)[source]

Return a number suitably formatted for display as currency, with thousands separated by commas and up to two decimal points.

>>> format_currency(1000)
u'1,000'
>>> format_currency(100)
u'100'
>>> format_currency(999.95)
u'999.95'
>>> format_currency(99.95)
u'99.95'
>>> format_currency(100000)
u'100,000'
>>> format_currency(1000.00)
u'1,000'
>>> format_currency(1000.41)
u'1,000.41'
>>> format_currency(23.21, decimals=3)
u'23.210'
>>> format_currency(1000, decimals=3)
u'1,000'
>>> format_currency(123456789.123456789)
u'123,456,789.12'
coaster.utils.get_email_domain(email)[source]

Return the domain component of an email address. Returns None if the provided string cannot be parsed as an email address.

>>> get_email_domain('test@example.com')
'example.com'
>>> get_email_domain('test+trailing@example.com')
'example.com'
>>> get_email_domain('foobar')
>>> get_email_domain('foo@bar@baz')
>>> get_email_domain('foobar@')
>>> get_email_domain('@foobar')
coaster.utils.getbool(value)[source]

Returns a boolean from any of a range of values. Returns None for unrecognized values. Numbers other than 0 and 1 are considered unrecognized.

>>> getbool(True)
True
>>> getbool(1)
True
>>> getbool('1')
True
>>> getbool('t')
True
>>> getbool(2)
>>> getbool(0)
False
>>> getbool(False)
False
>>> getbool('n')
False
coaster.utils.make_name(text, delim=u'-', maxlength=50, checkused=None, counter=2)[source]

Generate an ASCII name slug. If a checkused filter is provided, it will be called with the candidate. If it returns True, make_name will add counter numbers starting from 2 until a suitable candidate is found.

Parameters:
  • delim (string) – Delimiter between words, default ‘-‘
  • maxlength (int) – Maximum length of name, default 50
  • checkused – Function to check if a generated name is available for use
  • counter (int) – Starting position for name counter
>>> make_name('This is a title')
'this-is-a-title'
>>> make_name('Invalid URL/slug here')
'invalid-url-slug-here'
>>> make_name('this.that')
'this-that'
>>> make_name('this:that')
'this-that'
>>> make_name("How 'bout this?")
'how-bout-this'
>>> make_name(u"How’s that?")
'hows-that'
>>> make_name(u'K & D')
'k-d'
>>> make_name('billion+ pageviews')
'billion-pageviews'
>>> make_name(u'हिन्दी slug!')
'hindii-slug'
>>> make_name(u'__name__', delim=u'_')
'name'
>>> make_name(u'how_about_this', delim=u'_')
'how_about_this'
>>> make_name(u'and-that', delim=u'_')
'and_that'
>>> make_name(u'Umlauts in Mötörhead')
'umlauts-in-motorhead'
>>> make_name('Candidate', checkused=lambda c: c in ['candidate'])
'candidate2'
>>> make_name('Candidate', checkused=lambda c: c in ['candidate'], counter=1)
'candidate1'
>>> make_name('Candidate', checkused=lambda c: c in ['candidate', 'candidate1', 'candidate2'], counter=1)
'candidate3'
>>> make_name('Long title, but snipped', maxlength=20)
'long-title-but-snipp'
>>> len(make_name('Long title, but snipped', maxlength=20))
20
>>> make_name('Long candidate', maxlength=10, checkused=lambda c: c in ['long-candi', 'long-cand1'])
'long-cand2'
>>> make_name(u'Lǝnkǝran')
'lankaran'
>>> make_name(u'example@example.com')
'example-example-com'
coaster.utils.make_password(password, encoding=u'BCRYPT')[source]

Make a password with PLAIN, SSHA or BCRYPT (default) encoding.

>>> make_password('foo', encoding='PLAIN')
u'{PLAIN}foo'
>>> make_password(u'bar', encoding='PLAIN')
u'{PLAIN}bar'
>>> make_password(u're-foo', encoding='SSHA')[:6]
u'{SSHA}'
>>> make_password('bar-foo', encoding='SSHA')[:6]
u'{SSHA}'
>>> make_password(u're-foo')[:8]
u'{BCRYPT}'
>>> make_password('bar-foo')[:8]
u'{BCRYPT}'
>>> make_password('foo') == make_password('foo')
False
>>> check_password(make_password('ascii'), 'ascii')
True
>>> check_password(make_password('mixed'), u'mixed')
True
>>> check_password(make_password(u'unicode'), u'unicode')
True
coaster.utils.md5sum(data)[source]

Return md5sum of data as a 32-character string.

>>> md5sum('random text')
'd9b9bec3f4cc5482e7c5ef43143e563a'
>>> md5sum(u'random text')
'd9b9bec3f4cc5482e7c5ef43143e563a'
>>> len(md5sum('random text'))
32
coaster.utils.namespace_from_url(url)[source]

Construct a dotted namespace string from a URL.

coaster.utils.newid()

Return a new random id that is exactly 22 characters long, by encoding a UUID4 in URL-safe Base64. See http://en.wikipedia.org/wiki/Base64#Variants_summary_table

>>> len(newid())
22
>>> newid() == newid()
False
>>> isinstance(newid(), unicode)
True
coaster.utils.newpin(digits=4)[source]

Return a random numeric string with the specified number of digits, default 4.

>>> len(newpin())
4
>>> len(newpin(5))
5
>>> newpin().isdigit()
True
coaster.utils.newsecret()[source]

Make a secret key for email confirmation and all that stuff. 44 characters long.

>>> len(newsecret())
44
>>> newsecret() == newsecret()
False
coaster.utils.nullint(value)[source]

Return int(value) if bool(value) is not False. Return None otherwise. Useful for coercing optional values to an integer.

>>> nullint('10')
10
>>> nullint('') is None
True
coaster.utils.nullstr(value)[source]

Return str(value) if bool(value) is not False. Return None otherwise. Useful for coercing optional values to a string.

>>> nullstr(10)
'10'
>>> nullstr('') is None
True
coaster.utils.nullunicode(value)[source]

Return unicode(value) if bool(value) is not False. Return None otherwise. Useful for coercing optional values to a string.

>>> nullunicode(10)
u'10'
>>> nullunicode('') is None
True
coaster.utils.sanitize_html(value, valid_tags={'em': [], 'pre': [], 'code': [], 'h3': [], 'h6': [], 'h4': [], 'h5': [], 'mark': [], 'strong': [], 'sub': [], 'img': ['src', 'width', 'height', 'align', 'alt'], 'ul': [], 'li': ['start'], 'sup': [], 'cite': [], 'dl': [], 'blockquote': [], 'hr': [], 'dd': [], 'ol': [], 'abbr': ['title'], 'br': [], 'dt': [], 'ins': [], 'a': ['href', 'title', 'target', 'rel'], 'b': [], 'i': [], 'p': [], 'del': []}, strip=True)[source]

Strips unwanted markup out of HTML.

coaster.utils.simplify_text(text)[source]

Simplify text to allow comparison.

>>> simplify_text("Awesome Coder wanted at Awesome Company")
'awesome coder wanted at awesome company'
>>> simplify_text("Awesome Coder, wanted  at Awesome Company! ")
'awesome coder wanted at awesome company'
>>> simplify_text(u"Awesome Coder, wanted  at Awesome Company! ")
u'awesome coder wanted at awesome company'
coaster.utils.sorted_timezones()[source]

Return a list of timezones sorted by offset from UTC.

coaster.utils.valid_username(candidate)[source]

Check if a username is valid.

>>> valid_username('example person')
False
>>> valid_username('example_person')
False
>>> valid_username('exampleperson')
True
>>> valid_username('example-person')
True
>>> valid_username('a')
True
>>> valid_username('a-') or valid_username('ab-') or valid_username('-a') or valid_username('-ab')
False

Related Topics

This Page