Repository: pydantic/pydantic

Issue:
Alias generator not working on inherited attributes
# Alias generator not working on inherited attributes
* OS: **Debian GNU/Linux 9 (stretch)**
* Python version `import sys; print(sys.version)`: **3.7.3**
* Pydantic version `import pydantic; print(pydantic.VERSION)`: **0.32.2**

On inherited attributes, the alias generators do not work, if the base class also has an alias generator set. Minimal example:

```py
from pydantic import BaseModel

def alias_generator_1(field_name: str) -> str:
    return field_name + '1'


def alias_generator_2(field_name: str) -> str:
    return field_name + '2'


class Base(BaseModel):
    x: int

    class Config:
        allow_population_by_alias = True
        alias_generator = alias_generator_1


class Impl(Base):
    y: int

    class Config(Base.Config):
        alias_generator = alias_generator_2


i = Impl(x=1, y=2)

# expected: {'x2': 1, 'y2': 2}
# actual: {'x1': 1, 'y2': 2}
print(i.dict(by_alias=True))
```


A simple fix is to just define the attribute again on the child like so:
```
class Impl(Base):
    x: int
    y: int

    class Config(Base.Config):
        alias_generator = alias_generator_2
```

But i would expect the `alias_generator` to be overridden for all attributes, when defined in subclasses.




Comments:
thanks for reporting, agreed it should apply to all fields.

Could you try on master or v1.0b2 and confirm if it's still broken?
Just tested it on `master` and can confirm it is still broken.

Patch:
diff --git a/docs/examples/alias_generator_config.py b/docs/examples/alias_generator_config.py
--- a/docs/examples/alias_generator_config.py
+++ b/docs/examples/alias_generator_config.py
@@ -5,12 +5,11 @@ def to_camel(string: str) -> str:
 
 class Voice(BaseModel):
     name: str
-    gender: str
     language_code: str
 
     class Config:
         alias_generator = to_camel
 
-voice = Voice(Name='Filiz', Gender='Female', LanguageCode='tr-TR')
+voice = Voice(Name='Filiz', LanguageCode='tr-TR')
 print(voice.language_code)
 print(voice.dict(by_alias=True))
diff --git a/docs/examples/alias_precedence.py b/docs/examples/alias_precedence.py
new file mode 100644
--- /dev/null
+++ b/docs/examples/alias_precedence.py
@@ -0,0 +1,21 @@
+from pydantic import BaseModel
+
+class Voice(BaseModel):
+    name: str
+    language_code: str
+
+    class Config:
+        @classmethod
+        def alias_generator(cls, string: str) -> str:
+            # this is the same as `alias_generator = to_camel` above
+            return ''.join(word.capitalize() for word in string.split('_'))
+
+class Character(Voice):
+    mood: str
+
+    class Config:
+        fields = {'mood': 'Mood', 'language_code': 'lang'}
+
+c = Character(Mood='happy', Name='Filiz', lang='tr-TR')
+print(c)
+print(c.dict(by_alias=True))
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -263,10 +263,10 @@ def infer(
 
     def set_config(self, config: Type['BaseConfig']) -> None:
         self.model_config = config
-        schema_from_config = config.get_field_info(self.name)
-        if schema_from_config:
+        info_from_config = config.get_field_info(self.name)
+        if info_from_config:
             self.field_info = cast(FieldInfo, self.field_info)
-            self.field_info.alias = self.field_info.alias or schema_from_config.get('alias') or self.name
+            self.field_info.alias = info_from_config.get('alias') or self.field_info.alias or self.name
             self.alias = cast(str, self.field_info.alias)
 
     @property


Test patch:
diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py
--- a/tests/test_edge_cases.py
+++ b/tests/test_edge_cases.py
@@ -1079,3 +1079,43 @@ class Model(BaseModel):
 
     assert Model().__fields__.keys() == {'v'}
     assert Model.__fields__.keys() == {'v'}
+
+
+def test_alias_child_precedence():
+    class Parent(BaseModel):
+        x: int
+
+        class Config:
+            fields = {'x': 'x1'}
+
+    class Child(Parent):
+        y: int
+
+        class Config:
+            fields = {'y': 'y2', 'x': 'x2'}
+
+    assert Child.__fields__['y'].alias == 'y2'
+    assert Child.__fields__['x'].alias == 'x2'
+
+
+def test_alias_generator_parent():
+    class Parent(BaseModel):
+        x: int
+
+        class Config:
+            allow_population_by_field_name = True
+
+            @classmethod
+            def alias_generator(cls, f_name):
+                return f_name + '1'
+
+    class Child(Parent):
+        y: int
+
+        class Config:
+            @classmethod
+            def alias_generator(cls, f_name):
+                return f_name + '2'
+
+    assert Child.__fields__['y'].alias == 'y2'
+    assert Child.__fields__['x'].alias == 'x2'