Repository: joke2k/faker

Issue:
sv_SE curreny provider missing
There are currently no provider for sv_SE handeling currencies.


Discussion:

Patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 2a02bbc6..2fbf53f8 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 4.4.0
+current_version = 4.5.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/CHANGELOG.rst b/CHANGELOG.rst
index 685d3604..fc6eaa70 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+`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/VERSION b/VERSION
index fdc66988..a84947d6 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-4.4.0
+4.5.0
diff --git a/docs/communityproviders.rst b/docs/communityproviders.rst
index b26dc41b..6d103a1b 100644
--- a/docs/communityproviders.rst
+++ b/docs/communityproviders.rst
@@ -12,10 +12,6 @@ Here's a list of Providers written by the community:
 |               | 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`_            |
@@ -41,7 +37,6 @@ 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/
diff --git a/docs/conf.py b/docs/conf.py
index 53ff5f27..6c21f786 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.5.0'
 # The full version, including alpha/beta/rc tags.
-release = '4.4.0'
+release = '4.5.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/faker/__init__.py b/faker/__init__.py
index 8f2c303c..b0da5d9f 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.5.0'
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"),
+    )


Test patch:
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