Repository: joke2k/faker

Issue:
Base provider methods are documented with the address provider.
In the docs the [BaseProvider methods](https://github.com/joke2k/faker/blob/master/faker/providers/__init__.py) are grouped with the [address provider](https://github.com/joke2k/faker/blob/master/faker/providers/address/__init__.py). Here is the documentation: http://faker.readthedocs.io/en/master/providers/faker.providers.address.html

I would expect those to be in their own category, and they have nothing to do with addresses.
Documentation of utilities like random_choices
Is there any online documentation of the utility functions like random_choices? I always end up looking at the source code when I forget what they're named.


Discussion:
Duplicate of #832 
@BrodyUnderwood1 That's what I've always been doing, but it's been difficult finding the information about e.g. `random_choices`, `random_int` or `random_letters` when you can't remember the names of them or know whether they even exist in the first place. Turns out, the documentation for them has been incorrectly placed under the `address` provider: https://faker.readthedocs.io/en/master/providers/faker.providers.address.html

It would be nice if they were documented in a more obvious place.
@BrodyUnderwood1 For future reference, I'd like for people to refrain from answers that sounds like 'Read the manual'. I'd rather have people link to the appropriate section of the docs instead.
The base provider methods being included in the address provider docs confused me at first. Even though I get why that happened, it is still a pain to look for the methods specific to the address provider because of all the other methods, and I still need to search the source code for specifics of the base provider methods. Personally, I prefer to have a separate page discussing the different base provider methods in more detail.

@fcurella I can probably take a swing at this, but I need to know if you agree with that structure.
@malefice Ideally. I'like to have a section with the methods shared by all providers (ie: `random_choices` et al). Then each provider would have a section with the methods that are guaranteed to be on all locales, followed by locale-specific methods.

Go ahead and see what you can come up with. Thank you so much for volunteering! :)


Resolving patch:
diff --git a/faker/build_docs.py b/faker/build_docs.py
--- a/faker/build_docs.py
+++ b/faker/build_docs.py
@@ -15,6 +15,12 @@ def write(fh, s):
     return fh.write(s.encode('utf-8'))
 
 
+def write_base_provider(fh, doc, base_provider):
+    formatters = doc.get_provider_formatters(base_provider)
+    write(fh, ':github_url: hide\n\n')
+    write_provider(fh, doc, base_provider, formatters)
+
+
 def write_provider(fh, doc, provider, formatters, excludes=None):
 
     if excludes is None:
@@ -47,16 +53,21 @@ def write_provider(fh, doc, provider, formatters, excludes=None):
 def write_docs(*args, **kwargs):
     from faker import Faker, documentor
     from faker.config import DEFAULT_LOCALE, AVAILABLE_LOCALES
-
-    fake = Faker(locale=DEFAULT_LOCALE)
-
     from faker.providers import BaseProvider
-    base_provider_formatters = [f for f in dir(BaseProvider)]
 
+    fake = Faker(locale=DEFAULT_LOCALE)
     doc = documentor.Documentor(fake)
 
-    formatters = doc.get_formatters(with_args=True, with_defaults=True)
+    # Write docs for fakers.providers.BaseProvider
+    base_provider = BaseProvider(fake)
+    fname = os.path.join(DOCS_ROOT, 'providers', 'BaseProvider.rst')
+    with open(fname, 'wb') as fh:
+        write_base_provider(fh, doc, base_provider)
 
+    # Write docs for default locale providers
+    base_provider_formatters = [f for f in dir(BaseProvider)]
+    formatters = doc.get_formatters(with_args=True, with_defaults=True,
+                                    excludes=base_provider_formatters)
     for provider, fakers in formatters:
         provider_name = doc.get_provider_name(provider)
         fname = os.path.join(DOCS_ROOT, 'providers', '%s.rst' % provider_name)
@@ -64,15 +75,18 @@ def write_docs(*args, **kwargs):
             write(fh, ':github_url: hide\n\n')
             write_provider(fh, doc, provider, fakers)
 
+    # Write providers index page
     with open(os.path.join(DOCS_ROOT, 'providers.rst'), 'wb') as fh:
         write(fh, ':github_url: hide\n\n')
         write(fh, 'Providers\n')
         write(fh, '=========\n')
         write(fh, '.. toctree::\n')
         write(fh, '   :maxdepth: 2\n\n')
+        write(fh, '   providers/BaseProvider\n')
         [write(fh, '   providers/%s\n' % doc.get_provider_name(provider))
          for provider, fakers in formatters]
 
+    # Write docs for locale-specific providers
     AVAILABLE_LOCALES = sorted(AVAILABLE_LOCALES)
     for lang in AVAILABLE_LOCALES:
         fname = os.path.join(DOCS_ROOT, 'locales', '%s.rst' % lang)
@@ -90,6 +104,7 @@ def write_docs(*args, **kwargs):
                                           excludes=base_provider_formatters):
                 write_provider(fh, d, p, fs)
 
+    # Write locales index page
     with open(os.path.join(DOCS_ROOT, 'locales.rst'), 'wb') as fh:
         write(fh, ':github_url: hide\n\n')
         write(fh, 'Locales\n')
diff --git a/faker/documentor.py b/faker/documentor.py
--- a/faker/documentor.py
+++ b/faker/documentor.py
@@ -22,7 +22,6 @@ def __init__(self, generator):
         self.already_generated = []
 
     def get_formatters(self, locale=None, excludes=None, **kwargs):
-
         self.max_name_len = 0
         self.already_generated = [] if excludes is None else excludes[:]
         formatters = []


Test patch: