diff --git a/docs/build/exec_examples.py b/docs/build/exec_examples.py
--- a/docs/build/exec_examples.py
+++ b/docs/build/exec_examples.py
@@ -91,7 +91,6 @@ def exec_examples():
     errors = []
     all_md = all_md_contents()
     new_files = {}
-    os.environ.clear()
     os.environ.update({'my_auth_key': 'xxx', 'my_api_key': 'xxx'})
 
     sys.path.append(str(EXAMPLES_DIR))
@@ -113,7 +112,7 @@ def error(desc: str):
         if f'{{!.tmp_examples/{file.name}!}}' not in all_md:
             error('file not used anywhere')
 
-        file_text = file.read_text()
+        file_text = file.read_text('utf-8')
         if '\n\n\n' in file_text:
             error('too many new lines')
         if not file_text.endswith('\n'):
@@ -184,7 +183,7 @@ def error(desc: str):
     print(f'writing {len(new_files)} example files to {TMP_EXAMPLES_DIR}')
     TMP_EXAMPLES_DIR.mkdir()
     for file_name, content in new_files.items():
-        (TMP_EXAMPLES_DIR / file_name).write_text(content)
+        (TMP_EXAMPLES_DIR / file_name).write_text(content, 'utf-8')
     gen_ansi_output()
     return 0
 
diff --git a/docs/examples/schema_extra_callable.py b/docs/examples/schema_extra_callable.py
new file mode 100644
--- /dev/null
+++ b/docs/examples/schema_extra_callable.py
@@ -0,0 +1,15 @@
+# output-json
+from typing import Dict, Any
+from pydantic import BaseModel
+
+class Person(BaseModel):
+    name: str
+    age: int
+
+    class Config:
+        @staticmethod
+        def schema_extra(schema: Dict[str, Any]) -> None:
+            for prop in schema.get('properties', {}).values():
+                prop.pop('title', None)
+
+print(Person.schema_json(indent=2))
diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -66,7 +66,7 @@ class BaseConfig:
     getter_dict: Type[GetterDict] = GetterDict
     alias_generator: Optional[Callable[[str], str]] = None
     keep_untouched: Tuple[type, ...] = ()
-    schema_extra: Dict[str, Any] = {}
+    schema_extra: Union[Dict[str, Any], Callable[[Dict[str, Any]], None]] = {}
     json_loads: Callable[[str], Any] = json.loads
     json_dumps: Callable[..., str] = json.dumps
     json_encoders: Dict[AnyType, AnyCallable] = {}
diff --git a/pydantic/schema.py b/pydantic/schema.py
--- a/pydantic/schema.py
+++ b/pydantic/schema.py
@@ -466,7 +466,11 @@ def model_process_schema(
         model, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix, known_models=known_models
     )
     s.update(m_schema)
-    s.update(model.__config__.schema_extra)
+    schema_extra = model.__config__.schema_extra
+    if callable(schema_extra):
+        schema_extra(s)
+    else:
+        s.update(schema_extra)
     return s, m_definitions, nested_models
 
 

I don't think we want more config options unless absolutely required.

The solution here is to allow `schema_extra` to be a function which can mutate the schema, #889. Happy to accept a PR for that. 
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -1482,6 +1482,22 @@ class Config:
     }
 
 
+def test_model_with_schema_extra_callable():
+    class Model(BaseModel):
+        name: str = None
+
+        class Config:
+            @staticmethod
+            def schema_extra(schema):
+                schema.pop('properties')
+                schema['type'] = 'override'
+
+    assert Model.schema() == {
+        'title': 'Model',
+        'type': 'override',
+    }
+
+
 def test_model_with_extra_forbidden():
     class Model(BaseModel):
         a: str

Supress title generation
# Feature Request

* OS: **Windows 10**
* Python version `import sys; print(sys.version)`: **3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]**
* Pydantic version `import pydantic; print(pydantic.VERSION)`: **1.2**

There's no way to suppress/opt-out of the `title` property generation in `schema()`.
```py
# main.py
import pprint

import pydantic

class User(pydantic.BaseModel):
    name: str = pydantic.Field(..., title="", description="User name")
    password: str = pydantic.Field(..., description="User password")
    age: int = pydantic.Field(..., title=None, description="User age")


pprint.pprint(User.schema())
```
spits out:
```py
{'properties': {'age': {'description': 'User age',
                        'title': 'Age',
                        'type': 'integer'},
                'name': {'description': 'User name',
                         'title': 'Name',
                         'type': 'string'},
                'password': {'description': 'User password',
                             'title': 'Password',
                             'type': 'string'}},
 'required': ['name', 'password', 'age'],
 'title': 'User',
 'type': 'object'}
```
notice how all `properties` are given the auto-generated `title`.

I care about this mostly as a [fastapi](https://github.com/tiangolo/fastapi) user. I don't like how Swagger UI renders the title, and find the title to be redundant with `description` anyway (although maybe I'm missing something?)

This can be seen by adding the following to the code above:
```py
import fastapi

app = fastapi.FastAPI()

@app.post("/users")
def create_user(user: User):
    pass
```
and running the server with `uvicorn main:app` (note this will require `pip install fastapi uvicorn`).
`http://127.0.0.1:8000/docs` show:
![image](https://user-images.githubusercontent.com/6503002/69888068-dfce4400-12e1-11ea-8c38-ded37bf97f5f.png)

If I patch `pydantic/schema.py` with the following:
```py
    schema_overrides = False
    # s = dict(title=field.field_info.title or field.alias.title().replace('_', ' '))
    s = {}
    if field.field_info.title:
```
the output is much nicer (IMO):

![image](https://user-images.githubusercontent.com/6503002/69888268-d1ccf300-12e2-11ea-8315-b5cbcf630806.png)

I'd be happy to submit a PR. Adding a `Config` option probably makes sense, but maybe there should also be a way to disable the auto-title only for a specific field? 

tests/test_schema.py::test_model_with_schema_extra_callable
tests/test_schema.py::test_key tests/test_schema.py::test_by_alias tests/test_schema.py::test_sub_model tests/test_schema.py::test_schema_class tests/test_schema.py::test_schema_repr tests/test_schema.py::test_schema_class_by_alias tests/test_schema.py::test_choices tests/test_schema.py::test_json_schema tests/test_schema.py::test_list_sub_model tests/test_schema.py::test_optional tests/test_schema.py::test_any tests/test_schema.py::test_set tests/test_schema.py::test_const_str tests/test_schema.py::test_const_false tests/test_schema.py::test_tuple[tuple-expected_schema0] tests/test_schema.py::test_tuple[field_type1-expected_schema1] tests/test_schema.py::test_tuple[field_type2-expected_schema2] tests/test_schema.py::test_bool tests/test_schema.py::test_strict_bool tests/test_schema.py::test_dict tests/test_schema.py::test_list tests/test_schema.py::test_list_union_dict[field_type0-expected_schema0] tests/test_schema.py::test_list_union_dict[field_type1-expected_schema1] tests/test_schema.py::test_list_union_dict[field_type2-expected_schema2] tests/test_schema.py::test_list_union_dict[field_type3-expected_schema3] tests/test_schema.py::test_list_union_dict[field_type4-expected_schema4] tests/test_schema.py::test_date_types[datetime-expected_schema0] tests/test_schema.py::test_date_types[date-expected_schema1] tests/test_schema.py::test_date_types[time-expected_schema2] tests/test_schema.py::test_date_types[timedelta-expected_schema3] tests/test_schema.py::test_str_basic_types[field_type0-expected_schema0] tests/test_schema.py::test_str_basic_types[field_type1-expected_schema1] tests/test_schema.py::test_str_basic_types[field_type2-expected_schema2] tests/test_schema.py::test_str_basic_types[field_type3-expected_schema3] tests/test_schema.py::test_str_constrained_types[StrictStr-expected_schema0] tests/test_schema.py::test_str_constrained_types[ConstrainedStr-expected_schema1] tests/test_schema.py::test_str_constrained_types[ConstrainedStrValue-expected_schema2] tests/test_schema.py::test_special_str_types[AnyUrl-expected_schema0] tests/test_schema.py::test_special_str_types[UrlValue-expected_schema1] tests/test_schema.py::test_email_str_types[EmailStr-email] tests/test_schema.py::test_email_str_types[NameEmail-name-email] tests/test_schema.py::test_secret_types[SecretBytes-string] tests/test_schema.py::test_secret_types[SecretStr-string] tests/test_schema.py::test_special_int_types[ConstrainedInt-expected_schema0] tests/test_schema.py::test_special_int_types[ConstrainedIntValue-expected_schema1] tests/test_schema.py::test_special_int_types[ConstrainedIntValue-expected_schema2] tests/test_schema.py::test_special_int_types[ConstrainedIntValue-expected_schema3] tests/test_schema.py::test_special_int_types[PositiveInt-expected_schema4] tests/test_schema.py::test_special_int_types[NegativeInt-expected_schema5] tests/test_schema.py::test_special_float_types[ConstrainedFloat-expected_schema0] tests/test_schema.py::test_special_float_types[ConstrainedFloatValue-expected_schema1] tests/test_schema.py::test_special_float_types[ConstrainedFloatValue-expected_schema2] tests/test_schema.py::test_special_float_types[ConstrainedFloatValue-expected_schema3] tests/test_schema.py::test_special_float_types[PositiveFloat-expected_schema4] tests/test_schema.py::test_special_float_types[NegativeFloat-expected_schema5] tests/test_schema.py::test_special_float_types[ConstrainedDecimal-expected_schema6] tests/test_schema.py::test_special_float_types[ConstrainedDecimalValue-expected_schema7] tests/test_schema.py::test_special_float_types[ConstrainedDecimalValue-expected_schema8] tests/test_schema.py::test_special_float_types[ConstrainedDecimalValue-expected_schema9] tests/test_schema.py::test_uuid_types[UUID-uuid] tests/test_schema.py::test_uuid_types[UUID1-uuid1] tests/test_schema.py::test_uuid_types[UUID3-uuid3] tests/test_schema.py::test_uuid_types[UUID4-uuid4] tests/test_schema.py::test_uuid_types[UUID5-uuid5] tests/test_schema.py::test_path_types[FilePath-file-path] tests/test_schema.py::test_path_types[DirectoryPath-directory-path] tests/test_schema.py::test_path_types[Path-path] tests/test_schema.py::test_json_type tests/test_schema.py::test_ipv4address_type tests/test_schema.py::test_ipv6address_type tests/test_schema.py::test_ipvanyaddress_type tests/test_schema.py::test_ipv4interface_type tests/test_schema.py::test_ipv6interface_type tests/test_schema.py::test_ipvanyinterface_type tests/test_schema.py::test_ipv4network_type tests/test_schema.py::test_ipv6network_type tests/test_schema.py::test_ipvanynetwork_type tests/test_schema.py::test_callable_type[annotation0] tests/test_schema.py::test_callable_type[annotation1] tests/test_schema.py::test_error_non_supported_types tests/test_schema.py::test_flat_models_unique_models tests/test_schema.py::test_flat_models_with_submodels tests/test_schema.py::test_flat_models_with_submodels_from_sequence tests/test_schema.py::test_model_name_maps tests/test_schema.py::test_schema_overrides tests/test_schema.py::test_schema_from_models tests/test_schema.py::test_schema_with_ref_prefix tests/test_schema.py::test_schema_no_definitions tests/test_schema.py::test_list_default tests/test_schema.py::test_dict_default tests/test_schema.py::test_constraints_schema[kwargs0-str-expected_extra0] tests/test_schema.py::test_constraints_schema[kwargs1-ConstrainedStrValue-expected_extra1] tests/test_schema.py::test_constraints_schema[kwargs2-str-expected_extra2] tests/test_schema.py::test_constraints_schema[kwargs3-bytes-expected_extra3] tests/test_schema.py::test_constraints_schema[kwargs4-str-expected_extra4] tests/test_schema.py::test_constraints_schema[kwargs5-int-expected_extra5] tests/test_schema.py::test_constraints_schema[kwargs6-int-expected_extra6] tests/test_schema.py::test_constraints_schema[kwargs7-int-expected_extra7] tests/test_schema.py::test_constraints_schema[kwargs8-int-expected_extra8] tests/test_schema.py::test_constraints_schema[kwargs9-int-expected_extra9] tests/test_schema.py::test_constraints_schema[kwargs10-float-expected_extra10] tests/test_schema.py::test_constraints_schema[kwargs11-float-expected_extra11] tests/test_schema.py::test_constraints_schema[kwargs12-float-expected_extra12] tests/test_schema.py::test_constraints_schema[kwargs13-float-expected_extra13] tests/test_schema.py::test_constraints_schema[kwargs14-float-expected_extra14] tests/test_schema.py::test_constraints_schema[kwargs15-Decimal-expected_extra15] tests/test_schema.py::test_constraints_schema[kwargs16-Decimal-expected_extra16] tests/test_schema.py::test_constraints_schema[kwargs17-Decimal-expected_extra17] tests/test_schema.py::test_constraints_schema[kwargs18-Decimal-expected_extra18] tests/test_schema.py::test_constraints_schema[kwargs19-Decimal-expected_extra19] tests/test_schema.py::test_unenforced_constraints_schema[kwargs0-int] tests/test_schema.py::test_unenforced_constraints_schema[kwargs1-float] tests/test_schema.py::test_unenforced_constraints_schema[kwargs2-Decimal] tests/test_schema.py::test_unenforced_constraints_schema[kwargs3-int] tests/test_schema.py::test_unenforced_constraints_schema[kwargs4-str] tests/test_schema.py::test_unenforced_constraints_schema[kwargs5-bytes] tests/test_schema.py::test_unenforced_constraints_schema[kwargs6-str] tests/test_schema.py::test_unenforced_constraints_schema[kwargs7-bool] tests/test_schema.py::test_unenforced_constraints_schema[kwargs9-type_9] tests/test_schema.py::test_unenforced_constraints_schema[kwargs10-ConstrainedListValue] tests/test_schema.py::test_constraints_schema_validation[kwargs0-str-foo] tests/test_schema.py::test_constraints_schema_validation[kwargs1-str-foo] tests/test_schema.py::test_constraints_schema_validation[kwargs2-bytes-foo] tests/test_schema.py::test_constraints_schema_validation[kwargs3-str-foo] tests/test_schema.py::test_constraints_schema_validation[kwargs4-int-3] tests/test_schema.py::test_constraints_schema_validation[kwargs5-int-3] tests/test_schema.py::test_constraints_schema_validation[kwargs6-int-3] tests/test_schema.py::test_constraints_schema_validation[kwargs7-int-2] tests/test_schema.py::test_constraints_schema_validation[kwargs8-int-3] tests/test_schema.py::test_constraints_schema_validation[kwargs9-int-3] tests/test_schema.py::test_constraints_schema_validation[kwargs10-int-5] tests/test_schema.py::test_constraints_schema_validation[kwargs11-float-3.0] tests/test_schema.py::test_constraints_schema_validation[kwargs12-float-2.1] tests/test_schema.py::test_constraints_schema_validation[kwargs13-float-3.0] tests/test_schema.py::test_constraints_schema_validation[kwargs14-float-4.9] tests/test_schema.py::test_constraints_schema_validation[kwargs15-float-3.0] tests/test_schema.py::test_constraints_schema_validation[kwargs16-float-2.0] tests/test_schema.py::test_constraints_schema_validation[kwargs17-float-3.0] tests/test_schema.py::test_constraints_schema_validation[kwargs18-float-5.0] tests/test_schema.py::test_constraints_schema_validation[kwargs19-float-3] tests/test_schema.py::test_constraints_schema_validation[kwargs20-float-3] tests/test_schema.py::test_constraints_schema_validation[kwargs21-Decimal-value21] tests/test_schema.py::test_constraints_schema_validation[kwargs22-Decimal-value22] tests/test_schema.py::test_constraints_schema_validation[kwargs23-Decimal-value23] tests/test_schema.py::test_constraints_schema_validation[kwargs24-Decimal-value24] tests/test_schema.py::test_constraints_schema_validation[kwargs25-Decimal-value25] tests/test_schema.py::test_constraints_schema_validation[kwargs26-Decimal-value26] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs0-str-foobar] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs1-str-f] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs2-str-bar] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs3-int-2] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs4-int-5] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs5-int-1] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs6-int-6] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs7-float-2.0] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs8-float-5.0] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs9-float-1.9] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs10-float-5.1] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs11-Decimal-value11] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs12-Decimal-value12] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs13-Decimal-value13] tests/test_schema.py::test_constraints_schema_validation_raises[kwargs14-Decimal-value14] tests/test_schema.py::test_schema_kwargs tests/test_schema.py::test_schema_dict_constr tests/test_schema.py::test_bytes_constrained_types[ConstrainedBytes-expected_schema0] tests/test_schema.py::test_bytes_constrained_types[ConstrainedBytesValue-expected_schema1] tests/test_schema.py::test_optional_dict tests/test_schema.py::test_optional_validator tests/test_schema.py::test_field_with_validator tests/test_schema.py::test_known_model_optimization tests/test_schema.py::test_root tests/test_schema.py::test_root_list tests/test_schema.py::test_root_nested_model tests/test_schema.py::test_new_type_schema tests/test_schema.py::test_literal_schema tests/test_schema.py::test_color_type tests/test_schema.py::test_model_with_schema_extra tests/test_schema.py::test_model_with_extra_forbidden tests/test_schema.py::test_enforced_constraints[int-kwargs0-field_schema0] tests/test_schema.py::test_enforced_constraints[annotation1-kwargs1-field_schema1] tests/test_schema.py::test_enforced_constraints[annotation2-kwargs2-field_schema2] tests/test_schema.py::test_enforced_constraints[annotation3-kwargs3-field_schema3] tests/test_schema.py::test_enforced_constraints[annotation4-kwargs4-field_schema4] tests/test_schema.py::test_enforced_constraints[annotation5-kwargs5-field_schema5] tests/test_schema.py::test_enforced_constraints[annotation6-kwargs6-field_schema6] tests/test_schema.py::test_enforced_constraints[annotation7-kwargs7-field_schema7] tests/test_schema.py::test_real_vs_phony_constraints tests/test_schema.py::test_conlist tests/test_schema.py::test_subfield_field_info tests/test_schema.py::test_dataclass