Repository: pydantic/pydantic

Issue:
BaseSettings alias config not working
pydantic version `0.14`

```
❯ export test=foobar; pipenv run python
Python 3.6.1 (default, Aug  1 2018, 10:30:03)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import pydantic
>>> class S(pydantic.BaseSettings):
...   test:str
...   class Config:
...     fields = dict(test=dict(alias="test"))
...
>>> S()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jasonkuhrt/.local/share/virtualenvs/waldo-QOik3jd4/lib/python3.6/site-packages/pydantic/env_settings.py", line 35, in __init__
    super().__init__(**values)
  File "/Users/jasonkuhrt/.local/share/virtualenvs/waldo-QOik3jd4/lib/python3.6/site-packages/pydantic/main.py", line 166, in __init__
    self.__setstate__(self._process_values(data))
  File "/Users/jasonkuhrt/.local/share/virtualenvs/waldo-QOik3jd4/lib/python3.6/site-packages/pydantic/main.py", line 331, in _process_values
    return validate_model(self, input_data)
  File "/Users/jasonkuhrt/.local/share/virtualenvs/waldo-QOik3jd4/lib/python3.6/site-packages/pydantic/main.py", line 507, in validate_model
    raise ValidationError(errors)
pydantic.error_wrappers.ValidationError: 1 validation error
test
  none is not an allow value (type=type_error.none.not_allowed)
>>> os.getenv('test')
'foobar'
```

Expected that `test` would be parsed as str of `foobar`.


Discussion:
This is a bug.

Because the alias `test` matches the name of the field, `field.alt_alias` 

https://github.com/samuelcolvin/pydantic/blob/cd50601172462b49cdf09e4d988906ba8f14af87/pydantic/env_settings.py#L43

Is `False`.

Shouldn't be too hard to fix. PR welcome, otherwise I'll fix when I get a chance.
Relatedly...

What drove the code sample above was a desire to change case semantics. Maybe there could be two options in config:

1. lower_case
2. upper_case (default)
3. case_insensitive

@samuelcolvin if you think you'd be open to this suggestion, I'll open a proper issue to further discuss it.
I'm very keen. I spend a lot of my time rewriting env variables to upper case.

The only slight problem I can see is that it's not entirely trivial to do the `case_insensitive` case, since env is case sensitive.

I guess the code could just do

```py
env2 = {k.lower(): v for k, v in os.environ.items()}
```
Then work with `env2`, but is there ever a chance that `os.environ` could be big enough to cause memory problems? I have no idea.

Resolving patch:
diff --git a/pydantic/env_settings.py b/pydantic/env_settings.py
--- a/pydantic/env_settings.py
+++ b/pydantic/env_settings.py
@@ -37,7 +37,7 @@ def _substitute_environ(self):
         """
         d = {}
         for field in self.__fields__.values():
-            if field.alt_alias:
+            if field.has_alias:
                 env_name = field.alias
             else:
                 env_name = self.__config__.env_prefix + field.name.upper()
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -62,6 +62,7 @@ class Field:
         'model_config',
         'name',
         'alias',
+        'has_alias',
         '_schema',
         'validate_always',
         'allow_none',
@@ -85,6 +86,7 @@ def __init__(
     ):
 
         self.name: str = name
+        self.has_alias: bool = bool(alias)
         self.alias: str = alias or name
         self.type_: type = type_
         self.class_validators = class_validators or []


Test patch:
diff --git a/tests/test_settings.py b/tests/test_settings.py
--- a/tests/test_settings.py
+++ b/tests/test_settings.py
@@ -98,3 +98,15 @@ class Settings(BaseSettings):
     env.set('APP_FOOBAR', 'xxx')
     s = Settings()
     assert s.foobar == 'xxx'
+
+
+def test_alias_matches_name(env):
+    class Settings(BaseSettings):
+        foobar: str
+
+        class Config:
+            fields = {'foobar': 'foobar'}
+
+    env.set('foobar', 'xxx')
+    s = Settings()
+    assert s.foobar == 'xxx'