Repository: joke2k/faker
Pull request #1295 (2020-10-03 14:58:14)

Split first names into male and female first names on pt_PT provider
### What does this changes

Corrects the first names when requested with gender specifications (e.g.: `fake.first_name_male()` and `fake.name_female()`).
 
### What was wrong

When, in example, `fake.name_male()` was requested, a female name is provided.

### How this fixes it

By spliting the female and male first names into seperate designated groups, it's possible to generate gender-specific names correctly. The last names are family names and are not gender-specific.



Patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 2a02bbc6..9cbbc71c 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 4.4.0
+current_version = 4.12.0
 files = VERSION faker/__init__.py docs/conf.py
 commit = True
 tag = True
diff --git a/.github/workflows/autobump.yml b/.github/workflows/autobump.yml
index 8559d029..2d0b55bb 100644
--- a/.github/workflows/autobump.yml
+++ b/.github/workflows/autobump.yml
@@ -29,7 +29,8 @@ jobs:
           githubToken: ${{ secrets.GITHUB_TOKEN }}
       - uses: actions/checkout@v2
         with:
-          fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
+         persist-credentials: false
+         fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
       - name: Get Next Version
         uses: "fcurella/gh-action-next-version@main"
         id: nextversion
diff --git a/.gitignore b/.gitignore
index ad8222c2..f3259eea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,4 @@ nosetests.xml
 *.iml
 *.ipr
 venv/
+.vscode
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 685d3604..79fbac89 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,47 @@
 Changelog
 =========
 
+`4.12.0 - 2020-10-13 <https://github.com/joke2k/faker/compare/v4.11.0...v4.12.0>`_
+----------------------------------------------------------------------------------
+
+* Geo provider added for ``tr_TR`` locale. Thanks @iamnotagentleman.
+
+`4.11.0 - 2020-10-13 <https://github.com/joke2k/faker/compare/v4.10.0...v4.11.0>`_
+----------------------------------------------------------------------------------
+
+* Add ``sk_SK`` Job provider. Thanks @pipozzz.
+
+`4.10.0 - 2020-10-13 <https://github.com/joke2k/faker/compare/v4.9.0...v4.10.0>`_
+---------------------------------------------------------------------------------
+
+* Add ``date_time`` provider for ``pt_PT``. Thanks @gplgps.
+
+`4.9.0 - 2020-10-08 <https://github.com/joke2k/faker/compare/v4.8.0...v4.9.0>`_
+-------------------------------------------------------------------------------
+
+* Add ``.unique()`` for unique values. Thanks @coiax.
+
+`4.8.0 - 2020-10-08 <https://github.com/joke2k/faker/compare/v4.7.0...v4.8.0>`_
+-------------------------------------------------------------------------------
+
+* Add automotive provider for ``tr_TR``. Thanks @molcay.
+
+`4.7.0 - 2020-10-08 <https://github.com/joke2k/faker/compare/v4.6.0...v4.7.0>`_
+-------------------------------------------------------------------------------
+
+* Add province list and add 2 new district to ``ne_NP``. Thanks @iamsauravsharma.
+
+
+`4.6.0 - 2020-10-08 <https://github.com/joke2k/faker/compare/v4.5.0...v4.6.0>`_
+-------------------------------------------------------------------------------
+
+* Add Currency provider for ``sv_SE``. Thanks @frangiz.
+
+`4.5.0 - 2020-10-06 <https://github.com/joke2k/faker/compare/v4.4.0...v4.5.0>`_
+-------------------------------------------------------------------------------
+
+* Add ``pt_PT`` credit card provider. Thanks @rubenandre.
+
 `4.4.0 - 2020-10-02 <https://github.com/joke2k/faker/compare/v4.3.0...v4.4.0>`_
 -------------------------------------------------------------------------------
 
diff --git a/README.rst b/README.rst
index 172bac71..e99f40db 100644
--- a/README.rst
+++ b/README.rst
@@ -310,6 +310,38 @@ By default all generators share the same instance of ``random.Random``, which
 can be accessed with ``from faker.generator import random``. Using this may
 be useful for plugins that want to affect all faker instances.
 
+Unique values
+-------------
+
+Through use of the ``.unique`` property on the generator, you can guarantee
+that any generated values are unique for this specific instance.
+
+.. code:: python
+
+   from faker import Faker
+   fake = Faker()
+   names = [fake.unique.first_name() for i in range(500)]
+   assert len(set(names)) == len(names)
+
+Calling ``fake.unique.clear()`` clears the already seen values.
+Note, to avoid infinite loops, after a number of attempts to find a unique
+value, Faker will throw a ``UniquenessException``. Beware of the `birthday
+paradox <https://en.wikipedia.org/wiki/Birthday_problem>`_, collisions
+are more likely than you'd think.
+
+
+.. code:: python
+
+   from faker import Faker
+
+   fake = Faker()
+   for i in range(3):
+        # Raises a UniquenessException
+        fake.unique.boolean()
+
+In addition, only hashable arguments and return values can be used
+with ``.unique``.
+
 Seeding the Generator
 ---------------------
 
diff --git a/VERSION b/VERSION
index fdc66988..815588ef 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.4.0
+4.12.0
diff --git a/docs/communityproviders.rst b/docs/communityproviders.rst
index b26dc41b..e4cd0ff5 100644
--- a/docs/communityproviders.rst
+++ b/docs/communityproviders.rst
@@ -8,24 +8,23 @@ Here's a list of Providers written by the community:
 +---------------+--------------------------+----------------------------------+
 | Provider name | Description              | URL                              |
 +===============+==========================+==================================+
-| WebProvider   | Web-related data such as | `faker_web`_                     +
-|               | mime-type and web server |                                  +
-|               | versions.                |                                  +
-+---------------+--------------------------+----------------------------------+
-| CloudProvider | Cloud-related data       | `faker_cloud`_                   +
-|               | generic or specialized   |                                  +
-|               | by cloud.                |                                  +
-+---------------+--------------------------+----------------------------------+
-| Wi-Fi ESSID   | Fake Wi-Fi ESSIDs.       | `faker_wifi_essid`_              +
-+---------------+--------------------------+----------------------------------+
 | Credit Score  | Fake credit score data   | `faker_credit_score`_            |
 |               | for testing purposes     |                                  |
 +---------------+--------------------------+----------------------------------+
 | Microservice  | Fake microservice names  | `faker_microservice`_            |
 +---------------+--------------------------+----------------------------------+
+| Posts         | Fake posts in markdown   | `mdgen`_                         |
+|               | format                   |                                  |
++---------------+--------------------------+----------------------------------+
 | Vehicle       | Fake vehicle information | `faker_vehicle`_                 |
 |               | includes Year Make Model |                                  |
 +---------------+--------------------------+----------------------------------+
+| WebProvider   | Web-related data such as | `faker_web`_                     +
+|               | mime-type and web server |                                  +
+|               | versions.                |                                  +
++---------------+--------------------------+----------------------------------+
+| Wi-Fi ESSID   | Fake Wi-Fi ESSIDs.       | `faker_wifi_essid`_              +
++---------------+--------------------------+----------------------------------+
 
 If you want to add your own provider to this list, please submit a Pull Request to our `repo`_.
 
@@ -41,8 +40,8 @@ In order to be inlcuded, your provider must satisfy these requirement:
 .. _repo: https://github.com/joke2k/faker/
 .. _OSI-Approved: https://opensource.org/licenses/alphabetical
 .. _faker_web: https://pypi.org/project/faker_web/
-.. _faker_cloud: https://pypi.org/project/faker-cloud/
 .. _faker_wifi_essid: https://pypi.org/project/faker-wifi-essid/
 .. _faker_credit_score: https://pypi.org/project/faker-credit-score/
 .. _faker_microservice: https://pypi.org/project/faker-microservice/
 .. _faker_vehicle: https://pypi.org/project/faker-vehicle/
+.. _mdgen: https://pypi.org/project/mdgen/
diff --git a/docs/conf.py b/docs/conf.py
index 53ff5f27..282e3c78 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -51,9 +51,9 @@ copyright = '2014, Daniele Faraglia'
 # built documents.
 #
 # The short X.Y version.
-version = '4.4.0'
+version = '4.12.0'
 # The full version, including alpha/beta/rc tags.
-release = '4.4.0'
+release = '4.12.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/fakerclass.rst b/docs/fakerclass.rst
index c7a13304..656b4c8b 100644
--- a/docs/fakerclass.rst
+++ b/docs/fakerclass.rst
@@ -287,3 +287,72 @@ a cheatsheet for new ``Faker`` in multiple locale mode.
     fake['ja_JP'].luzon_province()
 
 .. _the relevant PR: https://github.com/joke2k/faker/pull/1052#issuecomment-557170225
+
+
+Unique Values
+-------------
+
+New in version ``v4.2.0` is the ``.unique`` attribute on the
+``Faker`` proxy.
+
+Accessing provider methods through this attribute guarantees that
+the returned values are unique for the lifetime of the ``Faker`` instance.
+
+
+.. code:: python
+
+   import faker
+   
+   fake = faker.Faker()
+
+   numbers = set(fake.unique.random_int() for i in range(1000))
+   assert len(numbers) == 1000
+
+To clear already seen values, simply call ``fake.unique.clear()``, which will
+allow previous values generated to be returned again.
+
+Different argument signatures for provider methods do not share
+a uniqueness pool.
+
+
+.. code:: python
+
+   import faker
+   
+   fake = faker.Faker()
+
+   numbers = set(fake.unique.random_int(min=1, max=10) for i in range(10))
+   other_numbers = set(fake.unique.random_int(min=1, max=5) for i in range(5))
+
+   assert other_numbers.issubset(numbers)
+
+If the range of possible values generated by a provider function is small
+and the ``.unique`` attribute has been used, it's possible that no
+suitable unique value will be found after a certain number of iterations.
+
+To avoid infinite loops, at that point, a ``UniquenessException`` will
+be raised.
+
+
+.. code:: python
+
+   import faker
+   
+   fake = faker.Faker()
+
+   for i in range(3):
+        fake.unique.boolean()  # UniquenessException!
+
+
+As a final caveat, only hashable arguments and return values can be used
+with the ``.unique`` attribute, as it is backed internally by a set for
+fast membership testing.
+
+
+.. code:: python
+
+   import faker
+   
+   fake = faker.Faker()
+
+   fake.unique.profile()  # TypeError: unhashable type: 'dict'
diff --git a/faker/__init__.py b/faker/__init__.py
index 8f2c303c..8a3466d9 100644
--- a/faker/__init__.py
+++ b/faker/__init__.py
@@ -2,4 +2,4 @@ from faker.factory import Factory  # noqa F401
 from faker.generator import Generator  # noqa F401
 from faker.proxy import Faker  # noqa F401
 
-VERSION = '4.4.0'
+VERSION = '4.12.0'
diff --git a/faker/exceptions.py b/faker/exceptions.py
new file mode 100644
index 00000000..bb744b9a
--- /dev/null
+++ b/faker/exceptions.py
@@ -0,0 +1,8 @@
+class BaseFakerException(Exception):
+    """The base exception for all Faker exceptions."""
+
+
+class UniquenessException(BaseFakerException):
+    """To avoid infinite loops, after a certain number of attempts,
+    the "unique" attribute of the Proxy will throw this exception.
+    """
diff --git a/faker/providers/address/ne_NP/__init__.py b/faker/providers/address/ne_NP/__init__.py
index acff4d35..ecdb181e 100644
--- a/faker/providers/address/ne_NP/__init__.py
+++ b/faker/providers/address/ne_NP/__init__.py
@@ -502,6 +502,8 @@ class Provider(AddressProvider):
         'ईश्वरपुर',
     )
 
+    # district taken from
+    # https://www.election.gov.np/election/np/district-wise-constituency-map.html
     districts = (
         'अछाम',
         'अर्घाखाँची',
@@ -535,7 +537,8 @@ class Provider(AddressProvider):
         'धनकुटा',
         'धनुषा',
         'धादिङ',
-        'नवलपरासी',
+        'नवलपरासी (बर्दघाट सुस्ता पूर्व)',
+        'नवलपरासी (बर्दघाट सुस्ता पश्चिम)',
         'नुवाकोट',
         'पर्वत',
         'पर्सा',
@@ -559,7 +562,8 @@ class Provider(AddressProvider):
         'म्याग्दी',
         'रसुवा',
         'रामेछाप',
-        'रुकुम',
+        '‍रुकुम पूर्व',
+        'रुकुम पश्चिम',
         'रूपन्देही',
         'रोल्पा',
         'रौतहट',
@@ -580,6 +584,24 @@ class Provider(AddressProvider):
         'हुम्ला',
     )
 
+    # province taken from
+    # https://ne.wikipedia.org/wiki/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A4%BE_%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A4%A6%E0%A5%87%E0%A4%B6%E0%A4%B9%E0%A4%B0%E0%A5%82  # noqa: E501
+    provinces = (
+        'प्रदेश नं १',
+        'प्रदेश नं २',
+        'बाग्मती प्रदेश',
+        'गण्डकी प्रदेश',
+        'प्रदेश नं ५',
+        'कर्णाली प्रदेश',
+        'सुदूरपश्चिम प्रदेश',
+    )
+
+    def province(self):
+        """
+        :example सुदूरपश्चिम प्रदेश
+        """
+        return self.random_element(self.provinces)
+
     def district(self):
         """
         :example अछाम
@@ -588,7 +610,7 @@ class Provider(AddressProvider):
 
     def city(self):
         """
-        :example कावासोत
+        :example कावासोती
         """
         return self.random_element(self.cities)
 
diff --git a/faker/providers/automotive/tr_TR/__init__.py b/faker/providers/automotive/tr_TR/__init__.py
new file mode 100644
index 00000000..e5498b23
--- /dev/null
+++ b/faker/providers/automotive/tr_TR/__init__.py
@@ -0,0 +1,31 @@
+import re
+
+from .. import Provider as AutomotiveProvider
+
+
+class Provider(AutomotiveProvider):
+    """Implement automotive provider for ``tr_TR`` locale.
+
+    Sources:
+
+    - https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_Turkey
+    """
+
+    license_formats = (
+        '## ? ####',
+        '## ? #####',
+        '## ?? ###',
+        '## ?? ####',
+        '## ??? ##',
+        '## ??? ###',
+    )
+    ascii_uppercase_turkish = 'ABCDEFGHIJKLMNOPRSTUVYZ'
+
+    def license_plate(self) -> str:
+        """Generate a license plate."""
+        temp = re.sub(r'\?',
+                      lambda x: self.random_element(self.ascii_uppercase_turkish),
+                      self.random_element(self.license_formats))
+        temp = temp.replace('##', '{:02d}', 1)
+        temp = temp.format(self.random_element(range(1, 82)))
+        return self.numerify(temp)
diff --git a/faker/providers/credit_card/pt_PT/__init__.py b/faker/providers/credit_card/pt_PT/__init__.py
new file mode 100644
index 00000000..57f2e74f
--- /dev/null
+++ b/faker/providers/credit_card/pt_PT/__init__.py
@@ -0,0 +1,68 @@
+from collections import OrderedDict
+
+from .. import CreditCard
+from .. import Provider as CreditCardProvider
+
+
+class Provider(CreditCardProvider):
+    """Implementation of ``pt_PT`` locale credit card
+
+    For all methods that take ``card_type`` as an argument a random card type
+    will be used if the supplied value is ``None``. The list of valid card types
+    includes ``'visa'``, ``'mastercard'`` and ``'maestro'``.
+
+    Source: https://bincheck.org/portugal
+    """
+
+    prefix_visa = ['400131', '400190', '400817', '402192', '402947', '402956', '403005', '403006', '403007',
+                   '403008', '403271', '404520', '404530', '405758', '406170', '406475', '407548', '407549',
+                   '407575', '408237', '408239', '409842', '409843', '410000', '410344', '410345', '410553',
+                   '410557', '411635', '411700', '411701', '411869', '412487', '412488', '412489', '412657',
+                   '412782', '412990', '413014', '413793', '413871', '415158', '415159', '415170', '415171',
+                   '415174', '415175', '415194', '415195', '415238', '415272', '415273', '415403', '415404',
+                   '415405', '415440', '415441', '415569', '415920', '415961', '416952', '416963', '416970',
+                   '417005', '417091', '417092', '417337', '418847', '419022', '419682', '419683', '419684',
+                   '421149', '421510', '422080', '422240', '422241', '422414', '422417', '422597', '422869',
+                   '423392', '423393', '424118', '424184', '424208', '424661', '425509', '425510', '425906',
+                   '426150', '426360', '426370', '427256', '427304', '427729', '427770', '427867', '428139',
+                   '428184', '428185', '428186', '428187', '429711', '430240', '430241', '431926', '433390',
+                   '433391', '433511', '433512', '433513', '433599', '433618', '433622', '433966', '437886',
+                   '438257', '439070', '440637', '440644', '440645', '442664', '443977', '443978', '444224',
+                   '444227', '445961', '445962', '446140', '446144', '449389', '450915', '451156', '451166',
+                   '454755', '455250', '455290', '455292', '455658', '456811', '456812', '457031', '458058',
+                   '458059', '459432', '459433', '459449', '460340', '460341', '460342', '461247', '461248',
+                   '461249', '462731', '462732', '464406', '465964', '476066', '476067', '476068', '476069',
+                   '476070', '476071', '476329', '477920', '477921', '477922', '477947', '477989', '478062',
+                   '478063', '479702', '479736', '483088', '485672', '486449', '486457', '489434', '489485',
+                   '490772', '490830', '490831', '490832', '490841', '490863', '491213', '491546', '491547',
+                   '491613', '492194', '493402', '493480', '493800', '493801', '493830', '498800', '499968',
+                   '499969', '499986', '422239', '422041', '464409', '464408']
+
+    prefix_mastercard = ['510122', '510123', '512556', '518772', '519744', '519774', '520342', '524552',
+                         '524878', '525625', '525808', '526819', '527014', '528024', '529119', '530267',
+                         '530770', '532355', '536468', '541171', '541557', '542081', '542098', '542858',
+                         '543099', '543116', '543123', '544051', '544052', '544233', '547260', '547459',
+                         '548168', '548169', '552727', '552755', '553057', '554506', '554517', '554518',
+                         '556660', '557836', '557882', '557883', '557888']
+
+    prefix_maestro = ['501654', '501659', '670530', '670811', '670812', '676938', '676938', '677393',
+                      '677707', '670835', '670817']
+
+    credit_card_types = OrderedDict((
+        ('maestro', CreditCard('Maestro', prefix_maestro, 16, security_code='CVV2')),
+        ('mastercard', CreditCard('Mastercard', prefix_mastercard, 16, security_code='CVV2')),
+        ('visa', CreditCard('Visa', prefix_visa, 16, security_code='CVV2')),
+    ))
+
+    def credit_card_expire(self, start='now', end='+4y', date_format='%m/%y'):
+        """Generate a credit card expiry date.
+
+        This method uses |date_time_between| under the hood to generate the
+        expiry date, so the ``start`` and ``end`` arguments work in the same way
+        here as it would in that method. For the actual formatting of the expiry
+        date, |strftime| is used and ``date_format`` is simply passed
+        to that method.
+        """
+
+        expire_date = self.generator.date_time_between(start, end)
+        return expire_date.strftime(date_format)
diff --git a/faker/providers/currency/sv_SE/__init__.py b/faker/providers/currency/sv_SE/__init__.py
new file mode 100644
index 00000000..69919686
--- /dev/null
+++ b/faker/providers/currency/sv_SE/__init__.py
@@ -0,0 +1,178 @@
+from .. import Provider as CurrencyProvider
+
+# Names taken from https://www.iban.se/currency-codes
+
+
+class Provider(CurrencyProvider):
+    # Format: (code, name)
+    currencies = (
+        ("AED", "UAE Dirham"),
+        ("AFN", "Afghani"),
+        ("ALL", "Lek"),
+        ("AMD", "Armenisk Dram"),
+        ("ANG", "Gulden från Nederländska Antillerna"),
+        ("AOA", "Kwanza"),
+        ("ARS", "Argentinsk Peso"),
+        ("AUD", "Australisk Dollar"),
+        ("AWG", "Arubisk Florin"),
+        ("AZN", "Azerbajdzjansk Manat"),
+        ("BAM", "Konvertibel Mark"),
+        ("BBD", "Barbadosdollar"),
+        ("BDT", "Taka"),
+        ("BGN", "Bulgarisk Lev"),
+        ("BHD", "Bahraini Dinar"),
+        ("BIF", "Burundi-franc"),
+        ("BMD", "Bermuda-dollar"),
+        ("BND", "Brunei-dollar"),
+        ("BOB", "Boliviano"),
+        ("BOV", "Mvdol"),
+        ("BRL", "Brasilisk Real"),
+        ("BSD", "Bahamasdollar"),
+        ("BTN", "Ngultrum"),
+        ("BWP", "Pula"),
+        ("BYR", "Vitrysk Rubel"),
+        ("BZD", "Belize-dollar"),
+        ("CAD", "Kanadensisk Dollar"),
+        ("CDF", "Kongolesisk Franc"),
+        ("CHE", "WIR Euro"),
+        ("CHF", "Schweizerfranc"),
+        ("CHW", "WIR Franc"),
+        ("CLF", "Unidad de Fomento"),
+        ("CLP", "Chilensk Peso"),
+        ("CNY", "Yuan Renminbi"),
+        ("COP", "Colombiansk Peso"),
+        ("COU", "Unidad de Valor Real"),
+        ("CRC", "Costa Ricansk Colon"),
+        ("CUC", "Peso Convertible"),
+        ("CUP", "Kubansk Peso"),
+        ("CVE", "Kap Verde Escudo"),
+        ("CZK", "Tjeckisk Koruna"),
+        ("DJF", "Djibouti-franc"),
+        ("DKK", "Dansk Krone"),
+        ("DOP", "Dominicansk Peso"),
+        ("DZD", "Algerisk Dinar"),
+        ("EGP", "Egyptiskt pund"),
+        ("ERN", "Nakfa"),
+        ("ETB", "Etiopisk Birr"),
+        ("EUR", "Euro"),
+        ("FJD", "Fiji Dollar"),
+        ("FKP", "Pund från Falklandöarna"),
+        ("GBP", "Pund Sterling"),
+        ("GEL", "Lari"),
+        ("GHS", "Ghana Cedi"),
+        ("GIP", "Gibraltar-pund"),
+        ("GMD", "Dalasi"),
+        ("GNF", "Guinea-franc"),
+        ("GTQ", "Quetzal"),
+        ("GYD", "Guyana-dollar"),
+        ("HKD", "Hong Kong-dollar"),
+        ("HNL", "Lempira"),
+        ("HRK", "Kuna"),
+        ("HTG", "Gourde"),
+        ("HUF", "Forint"),
+        ("IDR", "Rupiah"),
+        ("ILS", "Ny Israelisk Shekel"),
+        ("INR", "Indisk Rupie"),
+        ("IQD", "Irakisk Dinar"),
+        ("IRR", "Iransk Rial"),
+        ("ISK", "Isländsk Krona"),
+        ("JMD", "Jamaica-dollar"),
+        ("JOD", "Jordanisk Dinar"),
+        ("JPY", "Yen"),
+        ("KES", "Kenyansk Shilling"),
+        ("KGS", "Som"),
+        ("KHR", "Riel"),
+        ("KMF", "Comoros-franc"),
+        ("KPW", "Nordkoreansk Won"),
+        ("KRW", "Won"),
+        ("KWD", "Kuwaiti Dinar"),
+        ("KYD", "Caymanöar-dollar"),
+        ("KZT", "Tenge"),
+        ("LAK", "Kip"),
+        ("LBP", "Libanesiskt pund"),
+        ("LKR", "Sri Lanka Rupie"),
+        ("LRD", "Liberiansk Dollar"),
+        ("LSL", "Loti"),
+        ("LYD", "Libysk Dinar"),
+        ("MAD", "Marockansk Dirham"),
+        ("MDL", "Moldavisk Leu"),
+        ("MGA", "Malagasy Ariary"),
+        ("MKD", "Denar"),
+        ("MMK", "Kyat"),
+        ("MNT", "Tugrik"),
+        ("MOP", "Pataca"),
+        ("MRO", "Ouguiya"),
+        ("MUR", "Mauritius Rupie"),
+        ("MVR", "Rufiyaa"),
+        ("MWK", "Kwacha"),
+        ("MXN", "Mexikansk Peso"),
+        ("MXV", "Mexikansk Unidad de Inversion (UDI)"),
+        ("MYR", "Malaysisk Ringgit"),
+        ("MZN", "Mozambique Metical"),
+        ("NAD", "Namibia Dollar"),
+        ("NGN", "Naira"),
+        ("NIO", "Cordoba Oro"),
+        ("NOK", "Norsk Krone"),
+        ("NOK", "Norwegian Krone"),
+        ("NPR", "Nepalesisk Rupie"),
+        ("NZD", "Nya Zealand-dollar"),
+        ("OMR", "Rial Omani"),
+        ("PAB", "Balboa"),
+        ("PEN", "Nuevo Sol"),
+        ("PGK", "Kina"),
+        ("PHP", "Filippinsk Peso"),
+        ("PKR", "Pakistansk Rupie"),
+        ("PLN", "Zloty"),
+        ("PYG", "Guarani"),
+        ("QAR", "Qatari Rial"),
+        ("RON", "Rumänsk Leu"),
+        ("RSD", "Serbisk Dinar"),
+        ("RUB", "Rysk Rubel"),
+        ("RWF", "Rwanda Franc"),
+        ("SAR", "Saudi Riyal"),
+        ("SBD", "Dollar från Salomonöarna"),
+        ("SCR", "Seychell-rupie"),
+        ("SDG", "Sudanesiskt pund"),
+        ("SEK", "Svensk Krona"),
+        ("SGD", "Singapore Dollar"),
+        ("SHP", "Saint Helena pund"),
+        ("SLL", "Leone"),
+        ("SOS", "Somalisk Shilling"),
+        ("SRD", "Surinam Dollar"),
+        ("SSP", "Sydsudanesiskt pund"),
+        ("STD", "Dobra"),
+        ("SVC", "El Salvador Colon"),
+        ("SYP", "Syriskt pund"),
+        ("SZL", "Lilangeni"),
+        ("THB", "Baht"),
+        ("TJS", "Somoni"),
+        ("TMT", "Turkmenistansk Ny Manat"),
+        ("TND", "Tunisisk Dinar"),
+        ("TOP", "Pa’anga"),
+        ("TRY", "Turkisk Lira"),
+        ("TTD", "Trinidad och Tobago Dollar"),
+        ("TWD", "Ny Taiwanesisk Dollar"),
+        ("TZS", "Tanzanisk Shilling"),
+        ("UAH", "Hryvnia"),
+        ("UGX", "Uganda Shilling"),
+        ("USD", "US Dollar"),
+        ("USN", "US Dollar (Nästa dag)"),
+        ("UYI", "Uruguay Peso en Unidades Indexadas (URUIURUI)"),
+        ("UYU", "Peso Uruguayo"),
+        ("UZS", "Uzbekistansk Sum"),
+        ("VEF", "Bolivar"),
+        ("VND", "Dong"),
+        ("VUV", "Vatu"),
+        ("WST", "Tala"),
+        ("XAF", "CFA Franc BEAC"),
+        ("XCD", "East Caribbean Dollar"),
+        ("XDR", "SDR (Särskild dragningsrätt)"),
+        ("XOF", "CFA Franc BCEAO"),
+        ("XPF", "CFP Franc"),
+        ("XSU", "Sucre"),
+        ("XUA", "ADB Beräkningsenhet"),
+        ("YER", "Yemeni Rial"),
+        ("ZAR", "Rand"),
+        ("ZMW", "Zambian Kwacha"),
+        ("ZWL", "Zimbabwe Dollar"),
+    )
diff --git a/faker/providers/date_time/pt_PT/__init__.py b/faker/providers/date_time/pt_PT/__init__.py
new file mode 100644
index 00000000..e853211f
--- /dev/null
+++ b/faker/providers/date_time/pt_PT/__init__.py
@@ -0,0 +1,37 @@
+from .. import Provider as DateTimeProvider
+
+
+class Provider(DateTimeProvider):
+
+    DAY_NAMES = {
+        "0": "domingo",
+        "1": "segunda-feira",
+        "2": "terça-feira",
+        "3": "quarta-feira",
+        "4": "quinta-feira",
+        "5": "sexta-feira",
+        "6": "sábado",
+    }
+
+    MONTH_NAMES = {
+        "01": "janeiro",
+        "02": "fevereiro",
+        "03": "março",
+        "04": "abril",
+        "05": "maio",
+        "06": "junho",
+        "07": "julho",
+        "08": "agosto",
+        "09": "setembro",
+        "10": "outubro",
+        "11": "novembro",
+        "12": "dezembro",
+    }
+
+    def day_of_week(self):
+        day = self.date("%w")
+        return self.DAY_NAMES[day]
+
+    def month_name(self):
+        month = self.month()
+        return self.MONTH_NAMES[month]
diff --git a/faker/providers/geo/tr_TR/__init__.py b/faker/providers/geo/tr_TR/__init__.py
new file mode 100644
index 00000000..56ff1ad9
--- /dev/null
+++ b/faker/providers/geo/tr_TR/__init__.py
@@ -0,0 +1,88 @@
+from .. import Provider as GeoProvider
+
+
+class Provider(GeoProvider):
+    # Source: https://tr.wikipedia.org/wiki/T%C3%BCrkiye%27nin_illeri
+    land_coords = (
+        ('37.003277000000004', '35.3261219', 'Adana',  'TR', 'Europe/Istanbul'),
+        ('37.7640008', '38.2764355', 'Adıyaman', 'TR', 'Europe/Istanbul'),
+        ('38.756850899999996', '30.538694399999997', 'Afyonkarahisar', 'TR', 'Europe/Istanbul'),
+        ('38.3705416', '34.026907', 'Aksaray', 'TR', 'Europe/Istanbul'),
+        ('40.6569451', '35.7727169', 'Amasya', 'TR', 'Europe/Istanbul'),
+        ('39.921521899999995', '32.8537929', 'Ankara', 'TR', 'Europe/Istanbul'),
+        ('36.9009641', '30.6954846', 'Antalya', 'TR', 'Europe/Istanbul'),
+        ('41.1102966', '42.7035585', 'Ardahan', 'TR', 'Europe/Istanbul'),
+        ('41.160506', '41.839862700000005', 'Artvin', 'TR', 'Europe/Istanbul'),
+        ('37.841300700000005', '27.832837400000003', 'Aydın', 'TR', 'Europe/Istanbul'),
+        ('39.7201318', '43.050038799999996', 'Ağrı', 'TR', 'Europe/Istanbul'),
+        ('39.6473917', '27.8879787', 'Balıkesir', 'TR', 'Europe/Istanbul'),
+        ('41.6338394', '32.3384354', 'Bartın', 'TR', 'Europe/Istanbul'),
+        ('37.7874104', '41.2573924', 'Batman', 'TR', 'Europe/Istanbul'),
+        ('40.25569', '40.224099', 'Bayburt', 'TR', 'Europe/Istanbul'),
+        ('40.1435101', '29.975291100000003', 'Bilecik', 'TR', 'Europe/Istanbul'),
+        ('38.8851831', '40.4965998', 'Bingöl', 'TR', 'Europe/Istanbul'),
+        ('38.4002185', '42.1081317', 'Bitlis', 'TR', 'Europe/Istanbul'),
+        ('40.733295299999995', '31.6110479', 'Bolu', 'TR', 'Europe/Istanbul'),
+        ('37.7248394', '30.288728600000002', 'Burdur', 'TR', 'Europe/Istanbul'),
+        ('40.1826036', '29.067565500000004', 'Bursa', 'TR', 'Europe/Istanbul'),
+        ('37.773483299999995', '29.087389399999996', 'Denizli', 'TR', 'Europe/Istanbul'),
+        ('37.9167321', '40.2225658', 'Diyarbakır', 'TR', 'Europe/Istanbul'),
+        ('40.8458611', '31.164851000000002', 'Düzce', 'TR', 'Europe/Istanbul'),
+        ('41.675932700000004', '26.5587225', 'Edirne', 'TR', 'Europe/Istanbul'),
+        ('38.5824771', '39.396179', 'Elazığ', 'TR', 'Europe/Istanbul'),
+        ('39.749605200000005', '39.4941023', 'Erzincan', 'TR', 'Europe/Istanbul'),
+        ('39.7581897', '41.4032241', 'Erzurum', 'TR', 'Europe/Istanbul'),
+        ('39.766681299999995', '30.5255947', 'Eskişehir', 'TR', 'Europe/Istanbul'),
+        ('37.0611756', '37.3793085', 'Gaziantep', 'TR', 'Europe/Istanbul'),
+        ('40.9148702', '38.3879289', 'Giresun', 'TR', 'Europe/Istanbul'),
+        ('40.4617844', '39.475733899999994', 'Gümüşhane', 'TR', 'Europe/Istanbul'),
+        ('37.574898', '43.73766', 'Hakkari', 'TR', 'Europe/Istanbul'),
+        ('36.202593900000004', '36.1603945', 'Hatay', 'TR', 'Europe/Istanbul'),
+        ('37.77035', '30.5556933', 'Isparta', 'TR', 'Europe/Istanbul'),
+        ('39.921566799999994', '44.0467724', 'Iğdır', 'TR', 'Europe/Istanbul'),
+        ('37.5812744', '36.927509', 'Kahramanmaraş', 'TR', 'Europe/Istanbul'),
+        ('41.1110349', '32.619390100000004', 'Karabük', 'TR', 'Europe/Istanbul'),
+        ('37.179244700000005', '33.222478100000004', 'Karaman', 'TR', 'Europe/Istanbul'),
+        ('40.605158', '43.0961734', 'Kars', 'TR', 'Europe/Istanbul'),
+        ('41.3765359', '33.7770087', 'Kastamonu', 'TR', 'Europe/Istanbul'),
+        ('38.7225274', '35.4874516', 'Kayseri', 'TR', 'Europe/Istanbul'),
+        ('36.718045000000004', '37.11688', 'Kilis', 'TR', 'Europe/Istanbul'),
+        ('40.765382', '29.9406983', 'Kocaeli', 'TR', 'Europe/Istanbul'),
+        ('37.8719963', '32.484401500000004', 'Konya', 'TR', 'Europe/Istanbul'),
+        ('39.4191505', '29.987292800000002', 'Kütahya', 'TR', 'Europe/Istanbul'),
+        ('41.7370223', '27.223552299999998', 'Kırklareli', 'TR', 'Europe/Istanbul'),
+        ('39.8485708', '33.5276222', 'Kırıkkale', 'TR', 'Europe/Istanbul'),
+        ('39.14611420000001', '34.1605587', 'Kırşehir', 'TR', 'Europe/Istanbul'),
+        ('38.3483098', '38.3178715', 'Malatya', 'TR', 'Europe/Istanbul'),
+        ('38.615502899999996', '27.4255716', 'Manisa', 'TR', 'Europe/Istanbul'),
+        ('37.341485399999996', '40.7476249', 'Mardin', 'TR', 'Europe/Istanbul'),
+        ('36.8117583', '34.6292679', 'Mersin', 'TR', 'Europe/Istanbul'),
+        ('37.1642053', '28.2624288', 'Muğla', 'TR', 'Europe/Istanbul'),
+        ('38.740370299999995', '41.4967451', 'Muş', 'TR', 'Europe/Istanbul'),
+        ('38.6223688', '34.713602200000004', 'Nevşehir', 'TR', 'Europe/Istanbul'),
+        ('37.971207899999996', '34.6775534', 'Niğde', 'TR', 'Europe/Istanbul'),
+        ('40.8292569', '37.4082764', 'Ordu', 'TR', 'Europe/Istanbul'),
+        ('37.073671000000004', '36.255941', 'Osmaniye', 'TR', 'Europe/Istanbul'),
+        ('41.022809', '40.519612', 'Rize', 'TR', 'Europe/Istanbul'),
+        ('40.7731834', '30.481606', 'Sakarya', 'TR', 'Europe/Istanbul'),
+        ('41.2889924', '36.329445899999996', 'Samsun', 'TR', 'Europe/Istanbul'),
+        ('37.931282', '41.939840000000004', 'Siirt', 'TR', 'Europe/Istanbul'),
+        ('42.0266698', '35.1506765', 'Sinop', 'TR', 'Europe/Istanbul'),
+        ('39.7503572', '37.0145185', 'Sivas', 'TR', 'Europe/Istanbul'),
+        ('40.986222999999995', '27.513944', 'Tekirdağ', 'TR', 'Europe/Istanbul'),
+        ('40.327746999999995', '36.5539494', 'Tokat', 'TR', 'Europe/Istanbul'),
+        ('41.0058605', '39.718092799999994', 'Trabzon', 'TR', 'Europe/Istanbul'),
+        ('39.1080631', '39.548196999999995', 'Tunceli', 'TR', 'Europe/Istanbul'),
+        ('38.6710838', '29.407250899999998', 'Uşak', 'TR', 'Europe/Istanbul'),
+        ('38.508360100000004', '43.374532200000004', 'Van', 'TR', 'Europe/Istanbul'),
+        ('40.6556669', '29.272909100000003', 'Yalova', 'TR', 'Europe/Istanbul'),
+        ('39.8205571', '34.8094917', 'Yozgat', 'TR', 'Europe/Istanbul'),
+        ('41.250324', '31.8389738', 'Zonguldak', 'TR', 'Europe/Istanbul'),
+        ('40.1534952', '26.4140933', 'Çanakkale', 'TR', 'Europe/Istanbul'),
+        ('40.5971947', '33.6212704', 'Çankırı', 'TR', 'Europe/Istanbul'),
+        ('40.54914960000001', '34.9602453', 'Çorum', 'TR', 'Europe/Istanbul'),
+        ('41.0096334', '28.9651646', 'İstanbul', 'TR', 'Europe/Istanbul'),
+        ('38.415342100000004', '27.144474', 'İzmir', 'TR', 'Europe/Istanbul'),
+        ('37.2595198', '39.0408174', 'Şanlıurfa', 'TR', 'Europe/Istanbul'),
+        ('37.455253000000006', '42.5212049', 'Şırnak', 'TR', 'Europe/Istanbul'),
+        )
diff --git a/faker/providers/job/sk_SK/__init__.py b/faker/providers/job/sk_SK/__init__.py
new file mode 100644
index 00000000..4fb402b5
--- /dev/null
+++ b/faker/providers/job/sk_SK/__init__.py
@@ -0,0 +1,513 @@
+from .. import Provider as JobProvider
+
+
+class Provider(JobProvider):
+    """Translated from Super class"""
+
+    jobs = (
+        'Administrátor, umenie',
+        'Administrátor, štátna služba',
+        'Advokát',
+        'Advokát pre ochranné známky',
+        'Akademický knihovník',
+        'Akupunkturista',
+        'Analytický chemik',
+        'Analytik finančného rizika',
+        'Angličtina ako lektorka cudzieho jazyka',
+        'Angličtina ako učiteľka druhého jazyka',
+        'Animátor',
+        'Arborista',
+        'Archeológ',
+        'Architekt',
+        'Architektonický technológ',
+        'Archivár',
+        'Arteterapeut',
+        'Asistent politika',
+        'Astronóm',
+        'Audiologický vedec',
+        'Automobilový inžinier',
+        'Autorizovaný likvidátor strát',
+        'Autorizovaný účtovník',
+        'Autorizovaný účtovník v oblasti verejných financií',
+        'Bankár',
+        'Banský inžinier',
+        'Barista',
+        'Biochemik, klinický',
+        'Biomedicínsky inžinier',
+        'Biomedicínsky vedec',
+        'Bylinkár',
+        'Bytový manažér / referent',
+        'Charitatívny úradník',
+        'Chemický inžinier',
+        'Chemik, analytický',
+        'Chiropraktik',
+        'Chirurg',
+        'Copywriter, reklama',
+        'Cytogenetik',
+        'Daňový poradca',
+        'Detská sestra',
+        'Detský psychoterapeut',
+        'Diagnostický rádiograf',
+        'Dietológ',
+        'Dizajnér, fúkané sklo / vitráž',
+        'Dizajnér, grafik',
+        'Dizajnér, interiér / priestor',
+        'Dizajnér, keramika / hrnčiarstvo',
+        'Dizajnér, multimédiá',
+        'Dizajnér, móda / oblečenie',
+        'Dizajnér, nábytok',
+        'Dizajnér, priemyselný / produkt',
+        'Dizajnér, televízia / film',
+        'Dizajnér, textil',
+        'Dizajnér, výstava / výstava',
+        'Dizajnér, šperky',
+        'Docent',
+        'Dodávateľ',
+        'Dospelý poradenský pracovník',
+        'Dozorca',
+        'Dramatický terapeut',
+        'Dôstojník obchodného námorníctva',
+        'Dôstojník pre ochranu prírody',
+        'Dôstojník pre výcvik a vzdelávanie ozbrojených síl',
+        'Editor funkcie časopisu',
+        'Ekológ',
+        'Ekonóm',
+        'Elektroinžinier',
+        'Embryológ, klinický',
+        'Energetický inžinier',
+        'Energetický manažér',
+        'Environmentálny manažér',
+        'Ergonóm',
+        'Farebný technológ',
+        'Farmaceut Spoločenstva',
+        'Farmakológ',
+        'Filmový / video editor',
+        'Financny kontrolor',
+        'Finančný manažér',
+        'Finančný obchodník',
+        'Finančný plánovač',
+        'Finančný poradca',
+        'Finančný riaditeľ',
+        'Firemná sekretárka',
+        'Fotograf',
+        'Fytoterapeut',
+        'Fyzik zdravia',
+        'Fyzik, lekár',
+        'Fyziologický vedec',
+        'Fyziológ cvičenia',
+        'Fyzioterapeut',
+        'Fúkač skla / dizajnér',
+        'Genetik, molekulárny',
+        'Geochemik',
+        'Geodet minerálov',
+        'Geodet poistného rizika',
+        'Geofyzik / terénny seizmológ',
+        'Geológ, strojárstvo',
+        'Geológ',
+        'Geovedec',
+        'Grafický dizajnér',
+        'Grafik',
+        'Hasič',
+        'Hematológ',
+        'Herec',
+        'Herpetológ',
+        'Hlavný marketingový riaditeľ',
+        'Homeopat',
+        'Hotelový manažér',
+        'Hudobník',
+        'Hudobný lektor',
+        'Hudobný terapeut',
+        'Hutník',
+        'Hydrogeológ',
+        'Hydrografický geodet',
+        'Hydrológ',
+        'Hygienik práce',
+        'IT konzultant',
+        'Ilustrátor',
+        'Imunológ',
+        'Informačný úradník',
+        'Investičný analytik',
+        'Investičný bankár, funkčný',
+        'Investičný bankár, podnikový',
+        'Inšpektor / hodnotiteľ reklamácií',
+        'Inšpektor historických budov / referent pamiatkovej starostlivosti',
+        'Inšpektor plánovania a rozvoja',
+        'Inšpektor zdravia a bezpečnosti',
+        'Inžinier budov',
+        'Inžinier elektroniky',
+        'Inžinier kontroly a prístrojového vybavenia',
+        'Inžinier poľnohospodárstva',
+        'Inžinier pre automobilový priemysel',
+        'Inžinier výrobných systémov',
+        'Inžinier, baníctvo',
+        'Inžinier, biomedicínsky',
+        'Inžinier, chemický',
+        'Inžinier, elektronika',
+        'Inžinier, elektrotechnik',
+        'Inžinier, energia',
+        'Inžinier, komunikácia',
+        'Inžinier, letecký',
+        'Inžinier, materiály',
+        'Inžinier, pozemok',
+        'Inžinier, poľnohospodár',
+        'Inžinier, riadenie a prístrojové vybavenie',
+        'Inžinier, ropa',
+        'Inžinier, statik',
+        'Inžinier, stavebné služby',
+        'Inžinier, stavebný (zmluvný)',
+        'Inžinier, stavebný inžinier (poradenstvo)',
+        'Inžinier, technický predaj',
+        'Inžinier, voda',
+        'Inžinier, vysielanie (prevádzka)',
+        'Inžinier, výroba',
+        'Inžinier, výroba',
+        'Inžinier, výrobné systémy',
+        'Inžinier, vŕtanie',
+        'Inžinier, web',
+        'Inžinier, údržba',
+        'Inžinier, údržba (IT)',
+        'Inžiniersky geológ',
+        'Kameraman',
+        'Kariérny informačný úradník',
+        'Kariérny poradca',
+        'Kariérny poradca pre vysokoškolské vzdelávanie',
+        'Kartograf',
+        'Klinický biochemik',
+        'Klinický cytogenetik',
+        'Klinický embryológ',
+        'Klinický molekulárny genetik',
+        'Klinický psychológ',
+        'Klinický vedec, histokompatibilita a imunogenetika',
+        'Knihovník',
+        'Knihovník, verejný',
+        'Kníhkupec',
+        'Komerčný / rezidenčný geodet',
+        'Komerčný záhradník',
+        'Komunikačný inžinier',
+        'Komunitný umelecký pracovník',
+        'Konateľ spoločnosti',
+        'Kontrolór',
+        'Konzervátor / reštaurátor nábytku',
+        'Konzervátor múzea / galérie',
+        'Konzervátor, múzeum / galéria',
+        'Konzervátor, nábytok',
+        'Konzultant pre dôchodky',
+        'Konzultácia so stavebným inžinierom',
+        'Koordinátor dobrovoľníctva',
+        'Kupujúci, maloobchod',
+        'Kurátor',
+        'Kurátor múzea / galérie',
+        'Kópia',
+        'Lektor ďalšieho vzdelávania',
+        'Lektor, vysokoškolské vzdelanie',
+        'Lektor, ďalšie vzdelávanie',
+        'Lekár všeobecného lekára',
+        'Lekár, nemocnica',
+        'Lekár, všeobecná prax',
+        'Lekárnik, komunita',
+        'Lekárnik, nemocnica',
+        'Lekársky fyzik',
+        'Lekársky ilustrátor',
+        'Lekársky obchodný zástupca',
+        'Lekársky sekretár',
+        'Lekársky technický pracovník',
+        'Letecký dispečer',
+        'Letecký inžinier',
+        'Letecký sprostredkovateľ',
+        'Lexikograf',
+        'Licencovaný dopravca',
+        'Lobista',
+        'Logistika / podpora / administratívny dôstojník ozbrojených síl',
+        'Manažér call centra',
+        'Manažér cestovnej kancelárie',
+        'Manažér divadelnej scény',
+        'Manažér farmy',
+        'Manažér fitnescentra',
+        'Manažér informačných systémov',
+        'Manažér komerčnej umeleckej galérie',
+        'Manažér logistiky a distribúcie',
+        'Manažér stravovania',
+        'Manažér umeleckej galérie',
+        'Manažér zariadení',
+        'Manažér zábavného parku',
+        'Manžérsky konzultant',
+        'Marketingový manažér',
+        'Materiálový inžinier',
+        'Mediálny plánovač',
+        'Meteorológ',
+        'Mikrobiológ',
+        'Moderátor, vysielanie',
+        'Morský vedec',
+        'Multimediálne programy',
+        'Módny návrhár',
+        'Najlepší chlapec',
+        'Nemocničný lekár',
+        'Nemocničný lekárnik',
+        'Neurochirurg',
+        'Novinár novín',
+        'Novinár časopisu',
+        'Novinár, noviny',
+        'Novinár, vysielanie',
+        'Novinár, časopis',
+        'Nákupca médií',
+        'Nákupca, priemyselný',
+        'Námorný architekt',
+        'Návrhár interiérov a priestorov',
+        'Návrhár nábytku',
+        'Návrhár výstavy',
+        'Návrhár šperkov',
+        'Návrhárka keramiky',
+        'Obchodník s akciami',
+        'Obchodník s dlhopismi',
+        'Obchodník s futures',
+        'Oceánograf',
+        'Ochranár, historické budovy',
+        'Odborník na životné prostredie',
+        'Odevný / textilný technológ',
+        'Odevný / textilný technológ',
+        'Onkológ',
+        'Operatívny výskumník',
+        'Operačný dôstojník diplomatických služieb',
+        'Operačný dôstojník ozbrojených síl',
+        'Optik, výdaj',
+        'Optometristu',
+        'Organizácia podujatia',
+        'Ortoptista',
+        'Osobný asistent',
+        'Osteopat',
+        'Očný lekár',
+        'Palubní sprievodcovia',
+        'Patent attorney',
+        'Patológ',
+        'Pedagogický psychológ',
+        'Pedikér',
+        'Personalista',
+        'Pilot leteckej spoločnosti',
+        'Plánovač dopravy',
+        'Plánovač reklamného účtu',
+        'Plánovač tlače',
+        'Podnikový investičný bankár',
+        'Podnikový pokladník',
+        'Poistný matematik',
+        'Poisťovací maklér',
+        'Poisťovateľ',
+        'Police officer',
+        'Poradca pre zdravie a bezpečnosť',
+        'Poradca pre životné prostredie',
+        'Poradenská pracovníčka',
+        'Poradenský psychológ',
+        'Posádka',
+        'Potravinársky technológ',
+        'Poľnohospodársky konzultant',
+        'Pracovník medzinárodnej pomoci / rozvoja',
+        'Pracovník pomoci',
+        'Pracovník rozvoja komunity',
+        'Pracovník s mládežou',
+        'Pracovný psychológ',
+        'Pracovný terapeut',
+        'Predajca',
+        'Prekladateľ',
+        'Prevádzkovateľ televíznej kamery',
+        'Prevádzkový geológ',
+        'Prevádzkový investičný bankár',
+        'Prevádzkový riaditeľ',
+        'Priemyselný / produktový dizajnér',
+        'Priemyselný kupujúci',
+        'Prieskumník trhu',
+        'Prieskumový pracovník',
+        'Probačný úradník',
+        'Producent, rádio',
+        'Producent, televízia / film / video',
+        'Production assistant, radio',
+        'Production assistant, television',
+        'Production designer, theatre/television/film',
+        'Production engineer',
+        'Production manager',
+        'Produktový dizajnér',
+        'Produktový manažér',
+        'Professor Emeritus',
+        'Programme researcher, broadcasting/film/video',
+        'Programmer, applications',
+        'Programmer, multimedia',
+        'Programmer, systems',
+        'Proofreader',
+        'Právnik',
+        'Právny tajomník',
+        'Prázdninový zástupca',
+        'Psychiatric nurse',
+        'Psychiatrist',
+        'Psychologist, clinical',
+        'Psychologist, counselling',
+        'Psychologist, educational',
+        'Psychologist, forensic',
+        'Psychologist, occupational',
+        'Psychologist, prison and probation services',
+        'Psychologist, sport and exercise',
+        'Psychoterapeut tanečného pohybu',
+        'Psychoterapeut',
+        'Pôda',
+        'Pôrodná asistentka',
+        'Manažér kvality',
+        'Radca',
+        'Realitný maklér',
+        'Redaktor, uvedenie do prevádzky',
+        'Redakčný asistent',
+        'Referent cestovného ruchu',
+        'Referent environmentálnej výchovy',
+        'Referent geografických informačných systémov',
+        'Referent komunitného vzdelávania',
+        'Referent múzejného vzdelávania',
+        'Referent obchodných noriem',
+        'Referent ochrany prírody',
+        'Referent odbornej prípravy a rozvoja',
+        'Referent odborového výskumu',
+        'Referent poľných pokusov',
+        'Referent pre núdzové plánovanie / riadenie',
+        'Referent pre rovnosť a rozmanitosť',
+        'Referent pre výstavy v múzeách / galériách',
+        'Referent rozvoja umenia',
+        'Referent technickej podpory IT',
+        'Referent výstavy, múzeum / galéria',
+        'Referent ľudských zdrojov',
+        'Referent školstva pre životné prostredie',
+        'Referent školstva, komunita',
+        'Referent školstva, múzeum',
+        'Regulátor strát, objednaný',
+        'Reklamný textár',
+        'Reklamný umelecký riaditeľ',
+        'Riaditeľ pre stratégiu',
+        'Ropný inžinier',
+        'Rozvojový pracovník, komunita',
+        'Rozvojový pracovník, medzinárodná pomoc',
+        'Rýchly streamer pre štátnu službu',
+        'Sanitka',
+        'Sestra pre dospelých',
+        'Sestra pre duševné zdravie',
+        'Sestra s poruchami učenia',
+        'Sestra, detská',
+        'Sestra, dospelý',
+        'Sestra, porucha učenia',
+        'Sieťový inžinier',
+        'Spisovateľ',
+        'Spolupracovník pre klinický výskum',
+        'Spracovateľ geofyzikálnych údajov',
+        'Spravodajský analytik',
+        'Správca',
+        'Správca databázy',
+        'Správca dedičstva',
+        'Správca dôchodkového systému',
+        'Správca lesov a lesov',
+        'Správca nehnuteľnosti / pozemkový agent',
+        'Správca poistného účtu',
+        'Správca polohy',
+        'Správca spracovania údajov',
+        'Správca umenia',
+        'Správca zákazníckeho centra',
+        'Správca školstva',
+        'Správca štátnej služby',
+        'Správca, charitatívne / dobrovoľnícke organizácie',
+        'Správca, miestna samospráva',
+        'Správca, vzdelávanie',
+        'Správca, šport',
+        'Stavebný geodet',
+        'Stavebný geodet',
+        'Stavebný inžinier, poradenstvo',
+        'Stavebný inžinier, uzatváranie zmlúv',
+        'Strihač, film / video',
+        'Strojný inžinier',
+        'Strážca / strážca',
+        'Svetelný technik, vysielanie / film / video',
+        'Súdny psychológ',
+        'Súdny vedec',
+        'Súkromný učiteľ hudby',
+        'Tanečnica',
+        'Technický dôstojník ozbrojených síl',
+        'Technik údržby',
+        'Technológ pre zvieratá',
+        'Technológ varenia piva',
+        'Terapeut, dráma',
+        'Terapeut, hudba',
+        'Terapeut, záhradnícky',
+        'Terapeut, šport',
+        'Terénny seizmológ',
+        'Tlačový fotograf',
+        'Tlmočník',
+        'Toxikológ',
+        'Umelec',
+        'Urobiť',
+        'Uvádzací redaktor',
+        'Učiaci sa mentor',
+        'Učiteľ v ranom detstve',
+        'Učiteľ, angličtina ako cudzí jazyk',
+        'Učiteľ, hudba',
+        'Učiteľ, prvé roky / pred',
+        'Učiteľ, vzdelávanie dospelých',
+        'Učiteľ, základná škola',
+        'Učiteľka na základnej škole',
+        'Vedec dát',
+        'Vedec pre kvalitu vody',
+        'Vedec vývoja produktov / procesov',
+        'Vedecký pracovník lekárskeho laboratória',
+        'Vedúci kancelárie',
+        'Vedúci konferenčného centra',
+        'Vedúci osobnej dopravy',
+        'Vedúci outdoorových aktivít / vzdelávania',
+        'Vedúci reklamného účtu',
+        'Vedúci reštaurácie rýchleho občerstvenia',
+        'Vedúci rybej farmy',
+        'Vedúci skladu',
+        'Vedúci strediska voľného času',
+        'Vedúci turistického informačného centra',
+        'Vedúci ubytovania',
+        'Vedúci zdravotníckej služby',
+        'Vedúci úseku',
+        'Veterinárny chirurg',
+        'Video editor',
+        'Vizuálny obchodník',
+        'Vládny úradník pre sociálny výskum',
+        'Vodný inžinier',
+        'Vrtný inžinier',
+        'Vybavenie záhradník',
+        'Vybavovač poistných udalostí',
+        'Vysielaný novinár',
+        'Vysokoškolský lektor',
+        'Výdajný optik',
+        'Výkonný riaditeľ',
+        'Výkonný technický riaditeľ',
+        'Výrobný inžinier',
+        'Výtvarný umelec',
+        'Vývojár aplikácií',
+        'Vývojár hier',
+        'Vývojár počítačových hier',
+        'Vývojár systémov',
+        'Výživový poradca pre zvieratá',
+        'Výživový terapeut',
+        'Web dizajnér',
+        'Wellsite geológ',
+        'Zamestnanec imigračného úradu',
+        'Zdravotná sestra, duševné zdravie',
+        'Zdravotný návštevník',
+        'Zememerač / geomatik',
+        'Zmluvný stavebný inžinier',
+        'Zubár',
+        'Záchranár',
+        'Záhradnícky konzultant',
+        'Záhradnícky terapeut',
+        'Záhradník, komerčný',
+        'Záhradník, vybavenosť',
+        'Záhradný architekt',
+        'Záznamník bahna',
+        'Úradník miestnej samosprávy',
+        'Úradník pre rybolov',
+        'Účtovník, autorizované verejné financie',
+        'Účtovník, autorizovaný',
+        'Účtovník, autorizovaný certifikovaný',
+        'Účtovník, autorizovaný manažment',
+        'Účtovný technik',
+        'Špecialista na multimédiá',
+        'Špecialista na podporu zdravia',
+        'Špeditér',
+        'Šľachtiteľ rastlín / genetik')
+
+    def job(self):
+        return self.random_element(self.jobs)
diff --git a/faker/providers/person/pt_PT/__init__.py b/faker/providers/person/pt_PT/__init__.py
index a208572f..66709c83 100644
--- a/faker/providers/person/pt_PT/__init__.py
+++ b/faker/providers/person/pt_PT/__init__.py
@@ -2,52 +2,71 @@ from .. import Provider as PersonProvider
 
 
 class Provider(PersonProvider):
-    formats = (
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{last_name}}',
-        '{{first_name}} {{prefix}} {{last_name}}',
-        '{{first_name}} {{last_name}}-{{last_name}}',
-        '{{first_name}}-{{first_name}} {{last_name}}',
+    formats_male = (
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}',
+        '{{first_name_male}} {{prefix}} {{last_name}}',
+        '{{first_name_male}} {{last_name}}-{{last_name}}',
     )
 
-    first_names = (
-        'Adriana', 'Afonso', 'Alex', 'Alexandra', 'Alexandre', 'Alice',
-        'Alícia', 'Amélia', 'Ana', 'Andreia', 'André', 'Anita', 'António',
-        'Ariana', 'Artur', 'Beatriz', 'Benedita', 'Benjamim', 'Bernardo',
-        'Bianca', 'Brian', 'Bruna', 'Bruno', 'Bryan', 'Bárbara', 'Caetana',
-        'Camila', 'Carlos', 'Carlota', 'Carminho', 'Carolina', 'Catarina',
-        'Clara', 'Cláudio', 'Constança', 'Cristiano', 'César', 'Daniel',
-        'Daniela', 'David', 'Denis', 'Diana', 'Diego', 'Dinis', 'Diogo',
-        'Duarte', 'Débora', 'Edgar', 'Eduarda', 'Eduardo', 'Ema', 'Emanuel',
-        'Emma', 'Emília', 'Enzo', 'Erica', 'Erika', 'Eva', 'Fabiana',
-        'Fernando', 'Filipa', 'Filipe', 'Flor', 'Francisca', 'Francisco',
-        'Frederico', 'Fábio', 'Gabriel', 'Gabriela', 'Gaspar', 'Gil', 'Gonçalo',
-        'Guilherme', 'Gustavo', 'Helena', 'Henrique', 'Hugo', 'Iara', 'Igor',
-        'Inês', 'Irina', 'Isaac', 'Isabel', 'Isabela', 'Ivan', 'Ivo', 'Jaime',
-        'Joana', 'Joaquim', 'Joel', 'Jorge', 'José', 'João', 'Juliana',
-        'Jéssica', 'Júlia', 'Kelly', 'Kevin', 'Kyara', 'Kévim', 'Lara',
-        'Larissa', 'Laura', 'Leandro', 'Leonardo', 'Leonor', 'Letícia', 'Lia',
-        'Lisandro', 'Lorena', 'Lourenço', 'Luana', 'Luca', 'Lucas', 'Luciana',
-        'Luna', 'Luís', 'Luísa', 'Lúcia', 'Madalena', 'Mafalda', 'Manuel',
-        'Mara', 'Marco', 'Marcos', 'Margarida', 'Maria', 'Mariana', 'Marta',
-        'Martim', 'Mateus', 'Matias', 'Matilde', 'Mauro', 'Melissa', 'Mia',
-        'Micael', 'Miguel', 'Miriam', 'Márcio', 'Mário', 'Mélanie', 'Naiara',
-        'Nair', 'Nelson', 'Nicole', 'Noa', 'Noah', 'Nuno', 'Nádia', 'Núria',
-        'Patrícia', 'Paulo', 'Pedro', 'Petra', 'Pilar', 'Rafael', 'Rafaela',
-        'Raquel', 'Renata', 'Renato', 'Ricardo', 'Rita', 'Rodrigo', 'Rui',
-        'Rúben', 'Salomé', 'Salvador', 'Samuel', 'Sandro', 'Santiago', 'Sara',
-        'Sebastião', 'Simão', 'Sofia', 'Soraia', 'Sérgio', 'Tatiana', 'Teresa',
-        'Tiago', 'Tomás', 'Tomé', 'Valentim', 'Valentina', 'Vasco', 'Vera',
-        'Vicente', 'Victória', 'Violeta', 'Vitória', 'Vítor', 'William',
-        'Wilson', 'Xavier', 'Yara', 'Yasmin', 'Álvaro', 'Ângela', 'Ângelo',
-        'Érica', 'Íris',
+    formats_female = (
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}',
+        '{{first_name_female}} {{prefix}} {{last_name}}',
+        '{{first_name_female}} {{last_name}}-{{last_name}}',
+        '{{first_name_female}}-{{first_name_female}} {{last_name}}',
     )
 
+    formats = formats_male + formats_female
+
+    first_names_male = (
+        'Afonso', 'Alexandre', 'Álvaro', 'André', 'Ângelo', 'António', 'Artur',
+        'Benjamim', 'Bernardo', 'Brian', 'Bruno', 'Bryan', 'Carlos',
+        'Cláudio', 'Cristiano', 'César', 'Daniel', 'David', 'Denis',
+        'Diego', 'Dinis', 'Diogo', 'Duarte', 'Edgar', 'Eduardo', 'Emanuel',
+        'Enzo', 'Fernando', 'Filipe', 'Francisco', 'Frederico', 'Fábio',
+        'Gabriel', 'Gaspar', 'Gil', 'Gonçalo', 'Guilherme', 'Gustavo',
+        'Henrique', 'Hugo', 'Igor', 'Isaac', 'Ismael', 'Ivan', 'Ivo', 'Jaime',
+        'Joaquim', 'Joel', 'Jorge', 'José', 'João', 'Kevin', 'Kévim',
+        'Leandro', 'Leonardo', 'Lisandro', 'Lourenço', 'Luca', 'Lucas',
+        'Luís', 'Manuel', 'Marco', 'Marcos', 'Martim', 'Mateus',
+        'Matias', 'Mauro', 'Micael', 'Miguel', 'Márcio', 'Mário',
+        'Nelson', 'Noa', 'Noah', 'Nuno', 'Paulo', 'Pedro', 'Rafael',
+        'Renato', 'Ricardo', 'Rodrigo', 'Rui', 'Rúben', 'Salvador',
+        'Samuel', 'Sandro', 'Santiago', 'Sebastião', 'Simão', 'Sérgio', 'Tiago',
+        'Tomás', 'Tomé', 'Valentim', 'Vasco', 'Vicente', 'Vítor', 'William',
+        'Wilson', 'Xavier',
+    )
+
+    first_names_female = (
+        'Adriana', 'Alexandra', 'Alice', 'Alícia', 'Amélia', 'Ana', 'Andreia',
+        'Ângela', 'Anita', 'Ariana', 'Beatriz', 'Benedita', 'Bianca', 'Bruna',
+        'Bárbara', 'Caetana', 'Camila', 'Carlota', 'Carminho', 'Carolina',
+        'Catarina', 'Clara', 'Constança', 'Daniela', 'Diana', 'Débora', 'Eduarda',
+        'Ema', 'Emma', 'Emília', 'Erica', 'Érica', 'Erika', 'Eva', 'Fabiana',
+        'Filipa', 'Flor', 'Francisca', 'Gabriela', 'Helena', 'Iara', 'Inês',
+        'Irina', 'Íris', 'Isabel', 'Isabela', 'Joana', 'Juliana', 'Jéssica',
+        'Júlia', 'Kelly', 'Kyara', 'Lara', 'Larissa', 'Laura', 'Leonor', 'Letícia',
+        'Lia', 'Lorena', 'Luana', 'Luciana', 'Luna', 'Luísa', 'Lúcia', 'Madalena',
+        'Mafalda', 'Mara', 'Margarida', 'Maria', 'Mariana', 'Marta', 'Matilde',
+        'Melissa', 'Mia', 'Miriam', 'Mélanie', 'Naiara', 'Nair', 'Nicole', 'Nádia',
+        'Núria', 'Patrícia', 'Petra', 'Pilar', 'Rafaela', 'Raquel', 'Renata',
+        'Rita', 'Salomé', 'Sara', 'Sofia', 'Soraia', 'Tatiana', 'Teresa',
+        'Valentina', 'Vera', 'Victória', 'Violeta', 'Vitória', 'Yara', 'Yasmin',
+    )
+
+    first_names = first_names_male + first_names_female
+
     last_names = (
         'Abreu', 'Almeida', 'Alves', 'Amaral', 'Amorim', 'Andrade', 'Anjos',
         'Antunes', 'Araújo', 'Assunção', 'Azevedo', 'Baptista', 'Barbosa',
diff --git a/faker/proxy.py b/faker/proxy.py
index 67f261ef..d3910562 100644
--- a/faker/proxy.py
+++ b/faker/proxy.py
@@ -1,13 +1,17 @@
+import functools
 import random
 import re
 
 from collections import OrderedDict
 
 from faker.config import DEFAULT_LOCALE
+from faker.exceptions import UniquenessException
 from faker.factory import Factory
 from faker.generator import Generator
 from faker.utils.distribution import choices_distribution
 
+_UNIQUE_ATTEMPTS = 1000
+
 
 class Faker:
     """Proxy class capable of supporting multiple locales"""
@@ -23,6 +27,7 @@ class Faker:
                  generator=None, includes=None, **config):
         self._factory_map = OrderedDict()
         self._weights = None
+        self._unique_proxy = UniqueProxy(self)
 
         if isinstance(locale, str):
             locales = [locale.replace('-', '_')]
@@ -105,6 +110,10 @@ class Faker:
             factory = self._select_factory(attr)
             return getattr(factory, attr)
 
+    @property
+    def unique(self):
+        return self._unique_proxy
+
     def _select_factory(self, method_name):
         """
         Returns a random factory that supports the provider method
@@ -236,3 +245,44 @@ class Faker:
 
     def items(self):
         return self._factory_map.items()
+
+
+class UniqueProxy:
+    def __init__(self, proxy):
+        self._proxy = proxy
+        self._seen = {}
+        self._sentinel = object()
+
+    def clear(self):
+        self._seen = {}
+
+    def __getattr__(self, name: str):
+        obj = getattr(self._proxy, name)
+        if callable(obj):
+            return self._wrap(name, obj)
+        else:
+            raise TypeError("Accessing non-functions through .unique is not supported.")
+
+    def _wrap(self, name, function):
+        @functools.wraps(function)
+        def wrapper(*args, **kwargs):
+            key = (name, args, tuple(sorted(kwargs.items())))
+
+            generated = self._seen.setdefault(key, {self._sentinel})
+
+            # With use of a sentinel value rather than None, we leave
+            # None open as a valid return value.
+            retval = self._sentinel
+
+            for i in range(_UNIQUE_ATTEMPTS):
+                if retval not in generated:
+                    break
+                retval = function(*args, **kwargs)
+            else:
+                raise UniquenessException("Got duplicated values after {0:,} iterations.".format(_UNIQUE_ATTEMPTS))
+
+            generated.add(retval)
+
+            return retval
+
+        return wrapper


Test patch:
diff --git a/docs/pytest-fixtures.rst b/docs/pytest-fixtures.rst
index ef9e0233..7c44a983 100644
--- a/docs/pytest-fixtures.rst
+++ b/docs/pytest-fixtures.rst
@@ -9,8 +9,9 @@ Pytest Fixtures
        assert isinstance(faker.name(), str)
 
 Out of the box, the ``faker`` fixture returns a session-scoped ``Faker`` instance to be used across
-all tests in your test suite. This instance defaults to the ``en-US`` locale, and it is reseeded
-using a seed value of ``0`` prior to each test.
+all tests in your test suite. This instance defaults to the ``en-US`` locale, it is reseeded
+using a seed value of ``0`` prior to each test, and the ``.unique`` remembered generated values
+are cleared.
 
 To change the default locale, you can define a session-scoped autouse ``faker_session_locale``
 fixture in your top level ``conftest.py``. To change the default seed value, you define a
diff --git a/faker/contrib/pytest/plugin.py b/faker/contrib/pytest/plugin.py
index 48c0eea9..2d866db8 100644
--- a/faker/contrib/pytest/plugin.py
+++ b/faker/contrib/pytest/plugin.py
@@ -33,5 +33,6 @@ def faker(request):
     if 'faker_seed' in request.fixturenames:
         seed = request.getfixturevalue('faker_seed')
     fake.seed_instance(seed=seed)
+    fake.unique.clear()
 
     return fake
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 00000000..c6481d5f
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,1 @@
+pytest_plugins = ["pytester"]
diff --git a/tests/providers/test_address.py b/tests/providers/test_address.py
index 0494ccec..0aa21db7 100644
--- a/tests/providers/test_address.py
+++ b/tests/providers/test_address.py
@@ -981,6 +981,12 @@ class TestKoKr:
 class TestNeNp:
     """Test ne_NP address provider methods"""
 
+    def test_province(self, faker, num_samples):
+        for _ in range(num_samples):
+            province = faker.province()
+            assert isinstance(province, str)
+            assert province in NeNpAddressProvider.provinces
+
     def test_district(self, faker, num_samples):
         for _ in range(num_samples):
             district = faker.district()
diff --git a/tests/providers/test_automotive.py b/tests/providers/test_automotive.py
index 65bc0c34..a971f7d0 100644
--- a/tests/providers/test_automotive.py
+++ b/tests/providers/test_automotive.py
@@ -3,6 +3,7 @@ import re
 from faker.providers.automotive.de_DE import Provider as DeDeAutomotiveProvider
 from faker.providers.automotive.es_ES import Provider as EsEsAutomotiveProvider
 from faker.providers.automotive.ru_RU import Provider as RuRuAutomotiveProvider
+from faker.providers.automotive.tr_TR import Provider as TrTrAutomotiveProvider
 
 
 class _SimpleAutomotiveTestMixin:
@@ -155,7 +156,25 @@ class TestEsEs:
             assert self.old_format_pattern.match(plate)
             assert plate[:2] == "CA"
 
-    def test_plate_format(self, faker):
-        plate = faker.license_plate()
-        assert isinstance(plate, str)
-        assert self.new_format_pattern.match(plate) or self.old_format_pattern.match(plate)
+    def test_plate_format(self, faker, num_samples):
+        for _ in range(num_samples):
+            plate = faker.license_plate()
+            assert isinstance(plate, str)
+            assert self.new_format_pattern.match(plate) or self.old_format_pattern.match(plate)
+
+
+class TestTrTr(_SimpleAutomotiveTestMixin):
+    """Test tr_TR automotive provider methods"""
+    license_plate_pattern = re.compile(
+        r'\d{2} [A-Z] \d{4}|'
+        r'\d{2} [A-Z] \d{5}|'
+        r'\d{2} [A-Z]{2} \d{3}|'
+        r'\d{2} [A-Z]{2} \d{4}|'
+        r'\d{2} [A-Z]{3} \d{2}|'
+        r'\d{2} [A-Z]{3} \d{3}',
+    )
+
+    def perform_extra_checks(self, license_plate, match):
+        [city_code, letters, _] = license_plate.split(' ')
+        assert int(city_code) in range(1, 82)
+        assert all(letter in TrTrAutomotiveProvider.ascii_uppercase_turkish for letter in letters)
diff --git a/tests/providers/test_credit_card.py b/tests/providers/test_credit_card.py
index 11b3df83..6c2561eb 100644
--- a/tests/providers/test_credit_card.py
+++ b/tests/providers/test_credit_card.py
@@ -125,3 +125,26 @@ class TestRuRu:
             card_data = faker.credit_card_full().split('\n')
             assert re.match('[A-Za-z]+', card_data[1])
             assert card_data[4] in RuRuBankProvider.banks
+
+
+class TestPtPt:
+    """Test pt_PT credit card provider methods"""
+
+    visa_pattern = re.compile(r'4[0-9]{15}')
+    mastercard_pattern = re.compile(r'5[1-5][0-9]{14}')
+    maestro_pattern = re.compile(r'(50|67)[0-9]{14}')
+
+    def test_visa(self, faker, num_samples):
+        for _ in range(num_samples):
+            number = faker.credit_card_number('visa')
+            assert self.visa_pattern.fullmatch(number)
+
+    def test_mastercard(self, faker, num_samples):
+        for _ in range(num_samples):
+            number = faker.credit_card_number('mastercard')
+            assert self.mastercard_pattern.fullmatch(number)
+
+    def test_maestro(self, faker, num_samples):
+        for _ in range(num_samples):
+            number = faker.credit_card_number('maestro')
+            assert self.maestro_pattern.fullmatch(number)
diff --git a/tests/providers/test_currency.py b/tests/providers/test_currency.py
index d8823169..81bd2220 100644
--- a/tests/providers/test_currency.py
+++ b/tests/providers/test_currency.py
@@ -110,3 +110,25 @@ class TestEsEs:
         for _ in range(num_samples):
             name = faker.currency_name()
             assert name in self.currency_names
+
+
+class TestSvSe:
+    """Test sv_SE currency provider"""
+    num_samples = 100
+
+    @classmethod
+    def setup_class(cls):
+        from faker.providers.currency.sv_SE import Provider as SvSeCurrencyProvider
+        cls.provider = SvSeCurrencyProvider
+        cls.currencies = cls.provider.currencies
+        cls.currency_codes, cls.currency_names = tuple(zip(*cls.currencies))
+
+    def test_currency(self, faker, num_samples):
+        for _ in range(num_samples):
+            cur = faker.currency()
+            assert cur in self.currencies
+
+    def test_currency_name(self, faker, num_samples):
+        for _ in range(num_samples):
+            name = faker.currency_name()
+            assert name in self.currency_names
diff --git a/tests/providers/test_date_time.py b/tests/providers/test_date_time.py
index 98f33076..4be1edcb 100644
--- a/tests/providers/test_date_time.py
+++ b/tests/providers/test_date_time.py
@@ -25,6 +25,7 @@ from faker.providers.date_time.es_ES import Provider as EsEsProvider
 from faker.providers.date_time.hy_AM import Provider as HyAmProvider
 from faker.providers.date_time.it_IT import Provider as ItItProvider
 from faker.providers.date_time.pl_PL import Provider as PlProvider
+from faker.providers.date_time.pt_PT import Provider as PtPtProvider
 from faker.providers.date_time.ru_RU import Provider as RuProvider
 from faker.providers.date_time.sk_SK import Provider as SkSkProvider
 from faker.providers.date_time.ta_IN import Provider as TaInProvider
@@ -868,3 +869,18 @@ class TestTrTr(unittest.TestCase):
     def test_month(self):
         month = self.fake.month_name()
         assert month in TrTrProvider.MONTH_NAMES.values()
+
+
+class TestPtPt(unittest.TestCase):
+
+    def setUp(self):
+        self.fake = Faker('pt_PT')
+        Faker.seed(0)
+
+    def test_day(self):
+        day = self.fake.day_of_week()
+        assert day in PtPtProvider.DAY_NAMES.values()
+
+    def test_month(self):
+        month = self.fake.month_name()
+        assert month in PtPtProvider.MONTH_NAMES.values()
diff --git a/tests/providers/test_geo.py b/tests/providers/test_geo.py
index 137eafe1..f5463969 100644
--- a/tests/providers/test_geo.py
+++ b/tests/providers/test_geo.py
@@ -106,3 +106,9 @@ class TestPtPT(unittest.TestCase):
         nationality = self.fake.nationality()
         assert isinstance(nationality, str)
         assert nationality in PtPtProvider.nationalities
+
+
+class TestTrTr(TestEnUS):
+    def setUp(self):
+        self.fake = Faker('tr_TR')
+        Faker.seed(0)
diff --git a/tests/providers/test_job.py b/tests/providers/test_job.py
index 33edb985..5bca64ea 100644
--- a/tests/providers/test_job.py
+++ b/tests/providers/test_job.py
@@ -8,6 +8,7 @@ from faker.providers.job.ja_JP import Provider as JaJpJobProvider
 from faker.providers.job.ko_KR import Provider as KoKrJobProvider
 from faker.providers.job.pt_BR import Provider as PtBrJobProvider
 from faker.providers.job.pt_PT import Provider as PtPtJobProvider
+from faker.providers.job.sk_SK import Provider as SkSkJobProvider
 from faker.providers.job.tr_TR import Provider as TrTrJobProvider
 
 
@@ -84,13 +85,23 @@ class TestPtPt:
 
 
 class TestPtBr:
-    """Test de_DE job provider"""
+    """Test pt_BR job provider"""
 
     def test_job(self, faker, num_samples):
         for _ in range(num_samples):
             assert faker.job() in PtBrJobProvider.jobs
 
 
+class TestSkSk:
+    """Test sk_SK job provider"""
+
+    def test_job(self, faker, num_samples):
+        for _ in range(num_samples):
+            job = faker.job()
+            assert isinstance(job, str)
+            assert job in SkSkJobProvider.jobs
+
+
 class TestTrTr:
     """Test tr_TR job provider"""
 
diff --git a/tests/providers/test_person.py b/tests/providers/test_person.py
index 10773a93..eaee9165 100644
--- a/tests/providers/test_person.py
+++ b/tests/providers/test_person.py
@@ -16,6 +16,7 @@ from faker.providers.person.ne_NP import Provider as NeProvider
 from faker.providers.person.or_IN import Provider as OrINProvider
 from faker.providers.person.pl_PL import Provider as PlPLProvider
 from faker.providers.person.pl_PL import checksum_identity_card_number as pl_checksum_identity_card_number
+from faker.providers.person.pt_PT import Provider as PtPtProvider
 from faker.providers.person.ru_RU import Provider as RuProvider
 from faker.providers.person.ru_RU import translit
 from faker.providers.person.sv_SE import Provider as SvSEProvider
@@ -616,6 +617,26 @@ class TestEsES(unittest.TestCase):
         assert language_name in EsESProvider.language_names
 
 
+class TestPtPt(unittest.TestCase):
+    """Tests person in the pt_PT locale."""
+
+    def setUp(self):
+        self.fake = Faker('pt_PT')
+        Faker.seed(0)
+
+    def test_male_first_name(self):
+        first_name_male = self.fake.first_name_male()
+        assert first_name_male in PtPtProvider.first_names_male
+
+    def test_female_first_name(self):
+        first_name_female = self.fake.first_name_female()
+        assert first_name_female in PtPtProvider.first_names_female
+
+    def test_last_name(self):
+        last_name = self.fake.last_name()
+        assert last_name in PtPtProvider.last_names
+
+
 class TestUs(unittest.TestCase):
     """ Tests person in the en_US locale """
 
diff --git a/tests/pytest/test_unique_clear.py b/tests/pytest/test_unique_clear.py
new file mode 100644
index 00000000..4bf382c9
--- /dev/null
+++ b/tests/pytest/test_unique_clear.py
@@ -0,0 +1,37 @@
+def test_unique_clears(testdir):
+    """Successive uses of the `faker` pytest fixture have the
+    generated unique values cleared between functions."""
+
+    testdir.makepyfile(
+        """
+        import pytest
+        from faker.exceptions import UniquenessException
+
+        NUM_SAMPLES = 100
+
+        def test_fully_exhaust_unique_booleans(faker):
+            _dummy = [faker.boolean() for _ in range(NUM_SAMPLES)]
+
+            faker.unique.boolean()
+            faker.unique.boolean()
+            with pytest.raises(UniquenessException):
+                faker.unique.boolean()
+            _dummy = [faker.boolean() for _ in range(NUM_SAMPLES)]
+
+        def test_do_not_exhaust_booleans(faker):
+            faker.unique.boolean()
+
+        def test_fully_exhaust_unique_booleans_again(faker):
+            _dummy = [faker.boolean() for _ in range(NUM_SAMPLES)]
+
+            faker.unique.boolean()
+            faker.unique.boolean()
+            with pytest.raises(UniquenessException):
+                faker.unique.boolean()
+            _dummy = [faker.boolean() for _ in range(NUM_SAMPLES)]
+        """,
+    )
+
+    result = testdir.runpytest()
+
+    result.assert_outcomes(passed=3)
diff --git a/tests/test_proxy.py b/tests/test_proxy.py
index 2b48d2bf..44eb73d5 100644
--- a/tests/test_proxy.py
+++ b/tests/test_proxy.py
@@ -322,6 +322,7 @@ class TestFakerProxyClass:
         fake = Faker(['en_US', 'en_PH'])
         expected = set(dir(Faker) + [
             '_factories', '_locales', '_factory_map', '_weights',
+            '_unique_proxy',
         ])
         for factory in fake.factories:
             expected |= {
diff --git a/tests/test_unique.py b/tests/test_unique.py
new file mode 100644
index 00000000..f939a6ab
--- /dev/null
+++ b/tests/test_unique.py
@@ -0,0 +1,62 @@
+import pytest
+
+from faker import Faker
+from faker.exceptions import UniquenessException
+
+
+class TestUniquenessClass:
+    def test_uniqueness(self):
+        fake = Faker("en_US")
+
+        names = set()
+        # There are (at time of writing 690) first names in the
+        # US identity provider. Birthday paradox puts the chances of
+        # no duplicates in 250 selections as low enough to be impossible
+        for i in range(250):
+            first_name = fake.unique.first_name()
+            assert first_name not in names
+            names.add(first_name)
+
+    def test_sanity_escape(self):
+        fake = Faker()
+
+        # Those of you who are especially astute may realise
+        # there are only 2 booleans, so the third boolean cannot
+        # be unique.
+        with pytest.raises(UniquenessException, match=r"Got duplicated values after [\d,]+ iterations."):
+            for i in range(3):
+                _ = fake.unique.boolean()
+
+    def test_uniqueness_clear(self):
+        fake = Faker()
+
+        for i in range(2):
+            fake.unique.boolean()
+
+        fake.unique.clear()
+
+        # Because we cleared the generated values, this will not
+        # throw an exception
+        fake.unique.boolean()
+
+    def test_exclusive_arguments(self):
+        """Calls through the "unique" portal will only affect
+        calls with that specific function signature.
+        """
+        fake = Faker()
+
+        for i in range(10):
+            fake.unique.random_int(min=1, max=10)
+
+        # Different signature, so new pool. If they shared a pool
+        # this would throw a sanity exception
+        fake.unique.random_int(min=2, max=10)
+
+    def test_functions_only(self):
+        """Accessing non-functions through the `.unique` attribute
+        will throw a TypeError."""
+
+        fake = Faker()
+
+        with pytest.raises(TypeError, match="Accessing non-functions through .unique is not supported."):
+            fake.unique.locales