diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e795a0..fecadd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Features: - Add `prefix` parameter to `Env` constructor ([#384](https://github.com/sloria/environs/issues/384)). Thanks [arthurc0102](https://github.com/sloria/environs/issues/384) for the suggestion. +- Re-export `validate` module from marshmallow ([#385](https://github.com/sloria/environs/issues/385)). Bug fixes: diff --git a/README.md b/README.md index 8ba4fc6..124fd73 100644 --- a/README.md +++ b/README.md @@ -219,34 +219,35 @@ year = env.int("YEAR") # =>2020 # export NODE_ENV='invalid' # export EMAIL='^_^' -from environs import env, ValidationError -from marshmallow.validate import OneOf, Length, Email +from environs import env, validate, ValidationError -# simple validator -def validator(n): - if n <= 0: - raise ValidationError("Invalid value.") - - -env.int("TTL", validate=validator) -# => Environment variable "TTL" invalid: ['Invalid value.'] - - -# using marshmallow validators +# built-in validators (provided by marshmallow) env.str( "NODE_ENV", - validate=OneOf( + validate=validate.OneOf( ["production", "development"], error="NODE_ENV must be one of: {choices}" ), ) # => Environment variable "NODE_ENV" invalid: ['NODE_ENV must be one of: production, development'] # multiple validators -env.str("EMAIL", validate=[Length(min=4), Email()]) +env.str("EMAIL", validate=[validate.Length(min=4), validate.Email()]) # => Environment variable "EMAIL" invalid: ['Shorter than minimum length 4.', 'Not a valid email address.'] + + +# custom validator +def validator(n): + if n <= 0: + raise ValidationError("Invalid value.") + + +env.int("TTL", validate=validator) +# => Environment variable "TTL" invalid: ['Invalid value.'] ``` +`environs.validate` is equivalent to [`marshmallow.validate`](https://marshmallow.readthedocs.io/en/stable/marshmallow.validate.html), so you can use any of the validators provided by that module. + ## Deferred validation By default, a validation error is raised immediately upon calling a parser method for an invalid environment variable. diff --git a/examples/deferred_validation_example.py b/examples/deferred_validation_example.py index 140e242..7a786ac 100644 --- a/examples/deferred_validation_example.py +++ b/examples/deferred_validation_example.py @@ -1,9 +1,7 @@ import os from pprint import pprint -from marshmallow.validate import Email, Length, OneOf, Range - -from environs import Env, EnvValidationError +from environs import Env, EnvValidationError, validate os.environ["TTL"] = "-2" os.environ["NODE_ENV"] = "invalid" @@ -11,14 +9,14 @@ env = Env(eager=False) -TTL = env.int("TTL", validate=Range(min=0, max=100)) +TTL = env.int("TTL", validate=validate.Range(min=0, max=100)) NODE_ENV = env.str( "NODE_ENV", - validate=OneOf( + validate=validate.OneOf( ["production", "development"], error="NODE_ENV must be one of: {choices}" ), ) -EMAIL = env.str("EMAIL", validate=[Length(min=4), Email()]) +EMAIL = env.str("EMAIL", validate=[validate.Length(min=4), validate.Email()]) # This will raise an error with the combined validation messages try: diff --git a/examples/django_example.py b/examples/django_example.py index bf46f81..856e53d 100644 --- a/examples/django_example.py +++ b/examples/django_example.py @@ -10,9 +10,8 @@ import os from pprint import pprint -import environs +from environs import env -env = environs.Env() env.read_env() BASE_DIR = os.path.dirname(os.path.abspath(__file__)) diff --git a/examples/marshmallow_example.py b/examples/marshmallow_example.py index 41969e5..2b4faff 100644 --- a/examples/marshmallow_example.py +++ b/examples/marshmallow_example.py @@ -3,7 +3,7 @@ import marshmallow as ma -from environs import Env +from environs import env os.environ["STATIC_PATH"] = "app/static" @@ -16,7 +16,6 @@ def _serialize(self, value, *args, **kwargs): return str(value) -env = Env() env.parser_from_field("path", PathField) static_path = env.path("STATIC_PATH") diff --git a/examples/plugin_example.py b/examples/plugin_example.py index 5d3824b..ace14f4 100644 --- a/examples/plugin_example.py +++ b/examples/plugin_example.py @@ -3,7 +3,7 @@ from furl import furl as Furl from yarl import URL -from environs import Env +from environs import env ##### This is the beginning of the plugin code ##### @@ -28,7 +28,6 @@ def setup(env): # Our application activates the plugin using the setup function -env = Env() setup(env) # We now have the 'furl' and 'yurl' methods available diff --git a/examples/validation_example.py b/examples/validation_example.py index 3b61fa3..6af1a39 100644 --- a/examples/validation_example.py +++ b/examples/validation_example.py @@ -1,27 +1,16 @@ import os -from marshmallow.validate import Email, Length, OneOf - -from environs import Env, EnvError +from environs import EnvError, ValidationError, env, validate os.environ["TTL"] = "-2" os.environ["NODE_ENV"] = "invalid" os.environ["EMAIL"] = "^_^" - -env = Env() - -# simple validator -try: - env.int("TTL", validate=lambda n: n > 0) -except EnvError as err: - print(err) - -# marshmallow validator +# built-in validator try: env.str( "NODE_ENV", - validate=OneOf( + validate=validate.OneOf( ["production", "development"], error="NODE_ENV must be one of: {choices}" ), ) @@ -31,6 +20,19 @@ # multiple validators try: - env.str("EMAIL", validate=[Length(min=4), Email()]) + env.str("EMAIL", validate=[validate.Length(min=4), validate.Email()]) +except EnvError as err: + print(err) + + +# custom validator +def validate_ttl(value): + if value <= 0: + raise ValidationError("TTL must be greater than 0") + return value + + +try: + env.int("TTL", validate=validate_ttl) except EnvError as err: print(err) diff --git a/src/environs/__init__.py b/src/environs/__init__.py index aa24300..2484924 100644 --- a/src/environs/__init__.py +++ b/src/environs/__init__.py @@ -54,7 +54,9 @@ _EXPANDED_VAR_PATTERN = re.compile(r"(?