Miscellaneous utilities¶
-
coaster.utils.misc.
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.misc.
buid
()¶ Legacy name
-
coaster.utils.misc.
buid2uuid
(value)¶ Legacy name
-
coaster.utils.misc.
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.misc.
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) '1,000' >>> format_currency(100) '100' >>> format_currency(999.95) '999.95' >>> format_currency(99.95) '99.95' >>> format_currency(100000) '100,000' >>> format_currency(1000.00) '1,000' >>> format_currency(1000.41) '1,000.41' >>> format_currency(23.21, decimals=3) '23.210' >>> format_currency(1000, decimals=3) '1,000' >>> format_currency(123456789.123456789) '123,456,789.12'
-
coaster.utils.misc.
get_email_domain
(emailaddr)[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('Example Address <test@example.com>') 'example.com' >>> get_email_domain('foobar') >>> get_email_domain('foobar@') >>> get_email_domain('@foobar')
-
coaster.utils.misc.
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.misc.
is_collection
(item)[source]¶ Returns True if the item is a collection class: list, tuple, set, frozenset or any other class that resembles one of these (using abstract base classes).
>>> is_collection(0) False >>> is_collection(0.1) False >>> is_collection('') False >>> is_collection(b'') False >>> is_collection({}) False >>> is_collection({}.keys()) True >>> is_collection([]) True >>> is_collection(()) True >>> is_collection(set()) True >>> is_collection(frozenset()) True >>> from coaster.utils import InspectableSet >>> is_collection(InspectableSet({1, 2})) True
-
coaster.utils.misc.
make_name
(text, delim='-', 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: >>> 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("How’s that?") 'hows-that' >>> make_name('K & D') 'k-d' >>> make_name('billion+ pageviews') 'billion-pageviews' >>> make_name('हिन्दी slug!') 'hindii-slug' >>> make_name('Talk in español, Kiswahili, 廣州話 and অসমীয়া too.', maxlength=250) 'talk-in-espanol-kiswahili-guang-zhou-hua-and-asmiiyaa-too' >>> make_name('__name__', delim='_') 'name' >>> make_name('how_about_this', delim='_') 'how_about_this' >>> make_name('and-that', delim='_') 'and_that' >>> make_name('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('Lǝnkǝran') 'lankaran' >>> make_name('example@example.com') 'example-example-com' >>> make_name('trailing-delimiter', maxlength=10) 'trailing-d' >>> make_name('trailing-delimiter', maxlength=9) 'trailing' >>> make_name('''test this ... newline''') 'test-this-newline' >>> make_name("testing an emoji😁") 'testing-an-emoji' >>> make_name('''testing\t\nmore\r\nslashes''') 'testing-more-slashes' >>> make_name('What if a HTML <tag/>') 'what-if-a-html-tag' >>> make_name('These are equivalent to \x01 through \x1A') 'these-are-equivalent-to-through' >>> make_name("feedback;\x00") 'feedback'
-
coaster.utils.misc.
md5sum
(data)[source]¶ Return md5sum of data as a 32-character string.
>>> md5sum('random text') 'd9b9bec3f4cc5482e7c5ef43143e563a' >>> md5sum('random text') 'd9b9bec3f4cc5482e7c5ef43143e563a' >>> len(md5sum('random text')) 32
-
coaster.utils.misc.
nary_op
(f, doc=None)[source]¶ Decorator to convert a binary operator into a chained n-ary operator.
-
coaster.utils.misc.
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.misc.
newsecret
()[source]¶ Make a secret key for non-cryptographic use cases like email account verification. Mashes two UUID4s into a Base58 rendering, between 42 and 44 characters long. The resulting string consists of only ASCII strings and so will typically not be word-wrapped by email clients.
>>> len(newsecret()) in (42, 43, 44) True >>> newsecret() == newsecret() False
-
coaster.utils.misc.
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.misc.
nullstr
(value)[source]¶ Return unicode(value) if bool(value) is not False. Return None otherwise. Useful for coercing optional values to a string.
>>> nullstr(10) == '10' True >>> nullstr('') is None True
-
coaster.utils.misc.
require_one_of
(_return=False, **kwargs)[source]¶ Validator that raises
TypeError
unless one and only one parameter is notNone
. Use this inside functions that take multiple parameters, but allow only one of them to be specified:def my_func(this=None, that=None, other=None): # Require one and only one of `this` or `that` require_one_of(this=this, that=that) # If we need to know which parameter was passed in: param, value = require_one_of(True, this=this, that=that) # Carry on with function logic pass
Parameters: - _return – Return the matching parameter
- kwargs – Parameters, of which one and only one is mandatory
Returns: If _return, matching parameter name and value
Return type: tuple
Raises: TypeError – If the count of parameters that aren’t
None
is not 1
-
coaster.utils.misc.
unicode_http_header
(value)[source]¶ Convert an ASCII HTTP header string into a unicode string with the appropriate encoding applied. Expects headers to be RFC 2047 compliant.
>>> unicode_http_header('=?iso-8859-1?q?p=F6stal?=') == 'p\xf6stal' True >>> unicode_http_header(b'=?iso-8859-1?q?p=F6stal?=') == 'p\xf6stal' True >>> unicode_http_header('p\xf6stal') == 'p\xf6stal' True
-
coaster.utils.misc.
uuid1mc
()[source]¶ Return a UUID1 with a random multicast MAC id.
>>> isinstance(uuid1mc(), uuid.UUID) True
-
coaster.utils.misc.
uuid1mc_from_datetime
(dt)[source]¶ Return a UUID1 with a random multicast MAC id and with a timestamp matching the given datetime object or timestamp value.
Warning
This function does not consider the timezone, and is not guaranteed to return a unique UUID. Use under controlled conditions only.
>>> dt = datetime.now() >>> u1 = uuid1mc() >>> u2 = uuid1mc_from_datetime(dt) >>> # Both timestamps should be very close to each other but not an exact match >>> u1.time > u2.time True >>> u1.time - u2.time < 5000 True >>> d2 = datetime.fromtimestamp((u2.time - 0x01b21dd213814000) * 100 / 1e9) >>> d2 == dt True
-
coaster.utils.misc.
uuid2buid
(value)¶ Legacy name
-
coaster.utils.misc.
uuid_b58
()[source]¶ Return a UUID4 encoded in base58 and rendered as a string. Will be 21 or 22 characters long
>>> len(uuid_b58()) in (21, 22) True >>> uuid_b58() == uuid_b58() False >>> isinstance(uuid_b58(), str) True
-
coaster.utils.misc.
uuid_b64
()[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(buid()) 22 >>> buid() == buid() False >>> isinstance(buid(), str) True
-
coaster.utils.misc.
uuid_from_base58
(value)[source]¶ Convert a Base58-encoded UUID back into a UUID object
>>> uuid_from_base58('7KAmj837MyuJWUYPwtqAfz') UUID('33203dd2-f2ef-422f-aeb0-058d6f5f7089') >>> # The following UUID to Base58 encoding is from NPM uuid-base58, for comparison >>> uuid_from_base58('TedLUruK7MosG1Z88urTkk') UUID('d7ce8475-e77c-43b0-9dde-56b428981999')
-
coaster.utils.misc.
uuid_from_base64
(value)[source]¶ Convert a 22-char URL-safe Base64 string (BUID) to a UUID object
>>> uuid_from_base64('MyA90vLvQi-usAWNb19wiQ') UUID('33203dd2-f2ef-422f-aeb0-058d6f5f7089')
-
coaster.utils.misc.
uuid_to_base58
(value)[source]¶ Render a UUID in Base58 and return as a string
>>> uuid_to_base58(uuid.UUID('33203dd2-f2ef-422f-aeb0-058d6f5f7089')) '7KAmj837MyuJWUYPwtqAfz' >>> # The following UUID to Base58 encoding is from NPM uuid-base58, for comparison >>> uuid_to_base58(uuid.UUID('d7ce8475-e77c-43b0-9dde-56b428981999')) 'TedLUruK7MosG1Z88urTkk'
-
coaster.utils.misc.
uuid_to_base64
(value)[source]¶ Convert a UUID object to a 22-char URL-safe Base64 string (BUID)
>>> uuid_to_base64(uuid.UUID('33203dd2-f2ef-422f-aeb0-058d6f5f7089')) 'MyA90vLvQi-usAWNb19wiQ'
-
coaster.utils.misc.
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