diff --git a/.travis.yml b/.travis.yml index a604ab75..78c3377a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: python +sudo: false python: - "2.6" - "2.7" diff --git a/LICENSE.txt b/LICENSE.txt index 80d813f9..59010057 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2013 Daniele Faraglia +Copyright (c) 2013-2015, Daniele Faraglia Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.rst b/README.rst index 5e4be108..151f8d7c 100644 --- a/README.rst +++ b/README.rst @@ -125,7 +125,7 @@ How to install How to use ========== -There are only classes, Env and Path +There are only two classes, `environ.Env` and `environ.Path` :: @@ -166,6 +166,7 @@ Supported Types - float - json - list (FOO=a,b,c) +- tuple (FOO=(a,b,c)) - dict (BAR=key=val,foo=bar) - url - path (environ.Path) @@ -189,6 +190,7 @@ Supported Types - ElasticSearch: elasticsearch:// - Solr: solr:// - Whoosh: whoosh:// + - Xapian: xapian:// - Simple cache: simple:// - email_url - SMTP: smtp:// @@ -212,35 +214,39 @@ Tests License ======= -Django-environ is licensed under the MIT License - see the LICENSE.rst file for details +Django-environ is licensed under the MIT License - see the `LICENSE`_ file for details Changelog ========= -**0.4.0 (2015-09-19)** +`0.4.0 - 23-September-2015 `__ +------------------------------------------------------------------------------------------- - Fix non-ascii values (broken in Python 2.x) - New email schemes - smtp+ssl and smtp+tls (smtps would be deprecated) - redis_cache replaced by django_redis - -**0.3.1 (2014-09-03)** + - Add tuple support. Thanks to @anonymouzz - Add LDAP url support for database (django-ldapdb) - Fix psql/pgsql url -**0.3 (2014-06-03)** +`0.3 - 03-June-2014 `__ +-------------------------------------------------------------------------------------- - Add cache url support - Add email url support - Add search url support - Rewriting README.rst -**0.2.1 (2013-04-19)** +0.2.1 19-April-2013 +------------------- - environ/environ.py: Env.__call__ now uses Env.get_value instance method -**0.2 (2013-04-16)** +0.2 16-April-2013 +----------------- - environ/environ.py, environ/test.py, environ/test_env.txt: add advanced float parsing (comma and dot symbols to separate thousands and decimals) - README.rst, docs/index.rst: fix TYPO in documentation -**0.1 (2013-04-02)** +0.1 02-April-2013 +----------------- - initial release Credits @@ -311,3 +317,5 @@ Credits .. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square :target: https://raw.githubusercontent.com/joke2k/django-environ/master/LICENSE.txt :alt: Package license + +.. _LICENSE: https://github.com/joke2k/django-environ/blob/master/LICENSE.txt diff --git a/environ/environ.py b/environ/environ.py index e847cf98..ca07f93a 100644 --- a/environ/environ.py +++ b/environ/environ.py @@ -154,6 +154,12 @@ def list(self, var, cast=None, default=NOTSET): """ return self.get_value(var, cast=list if not cast else [cast], default=default) + def tuple(self, var, cast=None, default=NOTSET): + """ + :rtype: tuple + """ + return self.get_value(var, cast=tuple if not cast else (cast,), default=default) + def dict(self, var, cast=dict, default=NOTSET): """ :rtype: dict @@ -214,7 +220,9 @@ def get_value(self, var, cast=None, default=NOTSET, parse_default=False): :returns: Value from environment or default (if set) """ - logger.debug("get '{0}' casted as '{1}' with default '{2}'".format(var, cast, default)) + logger.debug("get '{0}' casted as '{1}' with default '{2}'".format( + var, cast, default + )) if var in self.scheme: var_info = self.scheme[var] @@ -251,7 +259,7 @@ def get_value(self, var, cast=None, default=NOTSET, parse_default=False): value = value.lstrip('$') value = self.get_value(value, cast=cast, default=default) - if value != default or parse_default: + if value != default or (parse_default and value): value = self.parse_value(value, cast) return value @@ -276,18 +284,27 @@ def parse_value(cls, value, cast): value = value.lower() in cls.BOOLEAN_TRUE_STRINGS elif isinstance(cast, list): value = list(map(cast[0], [x for x in value.split(',') if x])) + elif isinstance(cast, tuple): + val = value.strip('(').strip(')').split(',') + value = tuple(map(cast[0], [x for x in val if x])) elif isinstance(cast, dict): key_cast = cast.get('key', str) value_cast = cast.get('value', str) value_cast_by_key = cast.get('cast', dict()) value = dict(map( - lambda kv: (key_cast(kv[0]), cls.parse_value(kv[1], value_cast_by_key.get(kv[0], value_cast))), + lambda kv: ( + key_cast(kv[0]), + cls.parse_value(kv[1], value_cast_by_key.get(kv[0], value_cast)) + ), [val.split('=') for val in value.split(';') if val] )) elif cast is dict: value = dict([val.split('=') for val in value.split(',') if val]) elif cast is list: value = [x for x in value.split(',') if x] + elif cast is tuple: + val = value.strip('(').strip(')').split(',') + value = tuple([x for x in val if x]) elif cast is float: # clean string float_str = re.sub(r'[^\d,\.]', '', value) @@ -379,7 +396,7 @@ def cache_url_config(cls, url, backend=None): """Pulled from DJ-Cache-URL, parse an arbitrary Cache URL. :param url: - :param overrides: + :param backend: :return: """ url = urlparse.urlparse(url) if not isinstance(url, cls.URL_CLASS) else url @@ -663,7 +680,8 @@ def __sub__(self, other): return self.path('../' * other) elif isinstance(other, string_types): return Path(self.__root__.rstrip(other)) - raise TypeError("unsupported operand type(s) for -: '{0}' and '{1}'".format(self, type(other))) + raise TypeError( + "unsupported operand type(s) for -: '{0}' and '{1}'".format(self, type(other))) def __invert__(self): return self.path('..') @@ -683,11 +701,21 @@ def __str__(self): def __unicode__(self): return self.__str__() + def __getitem__(self, *args, **kwargs): + return self.__str__().__getitem__(*args, **kwargs) + + def rfind(self, *args, **kwargs): + return self.__str__().rfind(*args, **kwargs) + + def find(self, *args, **kwargs): + return self.__str__().find(*args, **kwargs) + @staticmethod def _absolute_join(base, *paths, **kwargs): absolute_path = os.path.abspath(os.path.join(base, *paths)) if kwargs.get('required', False) and not os.path.exists(absolute_path): - raise ImproperlyConfigured("Create required path: {0}".format(absolute_path)) + raise ImproperlyConfigured( + "Create required path: {0}".format(absolute_path)) return absolute_path diff --git a/environ/test.py b/environ/test.py index 80470ae4..7f66c349 100644 --- a/environ/test.py +++ b/environ/test.py @@ -37,6 +37,7 @@ def generateData(cls): BOOL_FALSE_VAR2='False', PROXIED_VAR='$STR_VAR', INT_LIST='42,33', + INT_TUPLE='(42,33)', STR_LIST_WITH_SPACES=' foo, bar', EMPTY_LIST='', DICT_VAR='foo=bar,test=on', @@ -109,6 +110,11 @@ def test_int_list(self): self.assertTypeAndValue(list, [42, 33], self.env('INT_LIST', cast=[int])) self.assertTypeAndValue(list, [42, 33], self.env.list('INT_LIST', int)) + def test_int_tuple(self): + self.assertTypeAndValue(tuple, (42, 33), self.env('INT_LIST', cast=(int,))) + self.assertTypeAndValue(tuple, (42, 33), self.env.tuple('INT_LIST', int)) + self.assertTypeAndValue(tuple, ('42', '33'), self.env.tuple('INT_LIST')) + def test_str_list_with_spaces(self): self.assertTypeAndValue(list, [' foo', ' bar'], self.env('STR_LIST_WITH_SPACES', cast=[str])) @@ -134,6 +140,7 @@ def test_url_value(self): url = self.env.url('URL_VAR') self.assertEqual(url.__class__, self.env.URL_CLASS) self.assertEqual(url.geturl(), self.URL) + self.assertEqual(None, self.env.url('OTHER_URL', default=None)) def test_db_url_value(self): pg_config = self.env.db() @@ -562,6 +569,10 @@ def test_comparison(self): self.assertTrue(Path('/home') == Path('/home')) self.assertTrue(Path('/home') != Path('/home/dev')) + self.assertEqual(Path('/home/foo/').rfind('/'), str(Path('/home/foo')).rfind('/')) + self.assertEqual(Path('/home/foo/').find('/home'), str(Path('/home/foo/')).find('/home')) + self.assertEqual(Path('/home/foo/')[1], str(Path('/home/foo/'))[1]) + self.assertEqual(~Path('/home'), Path('/')) self.assertEqual(Path('/') + 'home', Path('/home')) self.assertEqual(Path('/') + '/home/public', Path('/home/public')) diff --git a/environ/test_env.txt b/environ/test_env.txt index 875d6338..112ca3ea 100644 --- a/environ/test_env.txt +++ b/environ/test_env.txt @@ -24,3 +24,4 @@ STR_LIST_WITH_SPACES= foo, bar STR_VAR=bar INT_LIST=42,33 CYRILLIC_VAR=фуубар +INT_TUPLE=(42,33)