Repository: joke2k/faker
Pull request #2005 (2024-03-13 14:00:11)

Add more accepted formats
### What does this change

Adds a couple formats for belgians numbers.

### What was wrong

Missing commonly used formats.



Patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 440be344..8ff57188 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 24.1.0
+current_version = 24.2.1
 files = VERSION faker/__init__.py docs/conf.py
 commit = True
 tag = True
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 930a9553..7fb85fe2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
 ## Changelog
 
+### [v24.2.1 - 2024-03-18](https://github.com/joke2k/faker/compare/v24.2.0...v24.2.1)
+
+* return capitalized city names in `hu_HU`. Thanks @AlexLitvino.
+
+### [v24.2.0 - 2024-03-13](https://github.com/joke2k/faker/compare/v24.1.1...v24.2.0)
+
+* Add `uk-UA` credit card provider. Thanks @lozik4.
+* Upgrade `uk_UA` person provider. Thanks @lozik4.
+
+### [v24.1.1 - 2024-03-13](https://github.com/joke2k/faker/compare/v24.1.0...v24.1.1)
+
+* Fix prefix for male `bg_BG` names  Thanks @DimitarVanguelov.
+
 ### [v24.1.0 - 2024-03-08](https://github.com/joke2k/faker/compare/v24.0.0...v24.1.0)
 
 * Add Grenville to `land_coords` in geo provider. Thanks @lozik4.
diff --git a/VERSION b/VERSION
index 7c974b0f..8fadab05 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-24.1.0
+24.2.1
diff --git a/docs/conf.py b/docs/conf.py
index a12e8b76..9db83982 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -51,9 +51,9 @@ copyright = "2014-{0}, Daniele Faraglia".format(datetime.now().year)
 # built documents.
 #
 # The short X.Y version.
-version = "24.1.0"
+version = "24.2.1"
 # The full version, including alpha/beta/rc tags.
-release = "24.1.0"
+release = "24.2.1"
 
 # 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 33a6de25..c4791279 100644
--- a/faker/__init__.py
+++ b/faker/__init__.py
@@ -2,6 +2,6 @@ from faker.factory import Factory
 from faker.generator import Generator
 from faker.proxy import Faker
 
-VERSION = "24.1.0"
+VERSION = "24.2.1"
 
 __all__ = ("Factory", "Generator", "Faker")
diff --git a/faker/providers/address/hu_HU/__init__.py b/faker/providers/address/hu_HU/__init__.py
index 990f6379..54c7150d 100644
--- a/faker/providers/address/hu_HU/__init__.py
+++ b/faker/providers/address/hu_HU/__init__.py
@@ -467,3 +467,13 @@ class Provider(AddressProvider):
     def building_number(self) -> str:
         numeric_part = super().random_int(1, 250)
         return str(numeric_part) + "."
+
+    # method added to fix #1996:
+    # for hu_Hu locale city_part could be first or second component of city,
+    # so city_parts tuple should contain lower-cased strings. Thus city might be lower-cased and should be capitalized
+    def city(self) -> str:
+        """
+        :example: 'Györgyháza'
+        """
+        pattern: str = self.random_element(self.city_formats)
+        return self.generator.parse(pattern).capitalize()
diff --git a/faker/providers/bank/uk_UA/__init__.py b/faker/providers/bank/uk_UA/__init__.py
index 3b53dd45..ccf1b414 100644
--- a/faker/providers/bank/uk_UA/__init__.py
+++ b/faker/providers/bank/uk_UA/__init__.py
@@ -5,7 +5,83 @@ class Provider(BankProvider):
     """Implement bank provider for ``uk_UA`` locale.
     Source for rules for bban format:
     https://bank.gov.ua/en/iban
+    Banks list:
+    https://ubanks.com.ua/adr/
     """
 
     bban_format = "#" * 27
     country_code = "UA"
+    banks = (
+        "izibank",
+        "monobank",
+        "O.Bank",
+        "sportbank",
+        "А-Банк",
+        "Агропросперіс Банк",
+        "АкордБанк",
+        "Альтбанк",
+        "Асвіо Банк",
+        "Банк 3/4",
+        "Банк Авангард",
+        "Банк Альянс",
+        "Банк Власний Рахунок",
+        "Банк Восток",
+        "Банк інвестицій та заощаджень",
+        "Банк Кредит Дніпро",
+        "Банк Портал",
+        "Банк Український Капітал",
+        "Банк Фамільний",
+        "БТА Банк",
+        "Глобус",
+        "Грант",
+        "Дойче Банк ДБУ",
+        "Європейський Промисловий Банк",
+        "Ідея Банк",
+        "ІНГ Банк Україна",
+        "Індустріалбанк",
+        "Кліринговий Дім",
+        "Комінбанк",
+        "КомІнвестБанк",
+        "Кредит Європа Банк",
+        "Кредитвест Банк",
+        "Креді Агріколь",
+        "Кредобанк",
+        "Кристалбанк",
+        "Львів",
+        "МетаБанк",
+        "Міжнародний Інвестиційний Банк",
+        "Мотор-Банк",
+        "МТБ Банк",
+        "Національний банк України",
+        "Оксі Банк",
+        "ОТП Банк",
+        "Ощадбанк",
+        "Перший Інвестиційний Банк",
+        "Перший Український Міжнародний Банк",
+        "Південний",
+        "Піреус Банк",
+        "Полікомбанк",
+        "Полтава-Банк",
+        "Правекс Банк",
+        "ПриватБанк",
+        "ПроКредит Банк",
+        "Радабанк",
+        "Райффайзен Банк",
+        "РВС Банк",
+        "СЕБ Корпоративний Банк",
+        "Сенс Банк",
+        "Сітібанк",
+        "Скай Банк",
+        "ТАСкомбанк",
+        "Траст-капітал",
+        "Український банк реконструкції та розвитку",
+        "Укргазбанк",
+        "Укрексімбанк",
+        "УкрСиббанк",
+        "Універсал Банк",
+        "Юнекс Банк",
+    )
+
+    def bank(self) -> str:
+        """Generate a bank name."""
+        return self.random_element(self.banks)
diff --git a/faker/providers/credit_card/uk_UA/__init__.py b/faker/providers/credit_card/uk_UA/__init__.py
new file mode 100644
index 00000000..3ced3660
--- /dev/null
+++ b/faker/providers/credit_card/uk_UA/__init__.py
@@ -0,0 +1,58 @@
+from collections import OrderedDict
+from typing import Optional
+
+from faker.providers.person.uk_UA import translit
+
+from .. import CardType, CreditCard
+from .. import Provider as CreditCardProvider
+
+
+class Provider(CreditCardProvider):
+    """Implement credit card provider for ``uk_UA`` locale.
+    https://blog.ipay.ua/uk/sekrety-bankovskix-kart-kak-identificirovat-bank-po-nomeru-karty/
+    """
+
+    prefix_visa = ["4"]
+    prefix_mastercard = ["51", "52", "53", "54"]
+    prefix_prostir = ["9"]
+    prefix_maestro = ["6762"]
+
+    credit_card_types = OrderedDict(
+        (
+            ("visa", CreditCard("Visa", prefix_visa, security_code="CVV2")),
+            ("mastercard", CreditCard("Mastercard", prefix_mastercard, security_code="CVC2")),
+            ("prostir", CreditCard("ПРОСТІР", prefix_prostir, security_code="CVC2")),
+            ("maestro", CreditCard("Maestro", prefix_maestro, security_code="CVV")),
+        )
+    )
+
+    def credit_card_full(self, card_type: Optional[CardType] = None) -> str:
+        """Generate UA Credit Card:
+        Supported card types 'visa', 'mastercard', 'prostir', 'maestro'
+
+        :sample:
+        :sample: card_type="prostir"
+        :sample: card_type="mastercard"
+        """
+        card = self._credit_card_type(card_type)
+        tpl = "{provider}\n" "{owner}\n" "{number} {expire_date}\n" "{security}: {security_nb}\n" "{issuer}"
+        tpl = tpl.format(
+            provider=card.name,
+            owner=translit(
+                self.generator.parse(
+                    self.random_element(
+                        [
+                            "{{first_name_male}} {{last_name_male}}",
+                            "{{first_name_female}} {{last_name_female}}",
+                        ]
+                    )
+                )
+            ),
+            number=self.credit_card_number(card),
+            expire_date=self.credit_card_expire(),
+            security=card.security_code,
+            security_nb=self.credit_card_security_code(card),
+            issuer=self.generator.parse("{{bank}}"),
+        )
+
+        return self.generator.parse(tpl)
diff --git a/faker/providers/person/bg_BG/__init__.py b/faker/providers/person/bg_BG/__init__.py
index 7be27acc..69838ce9 100644
--- a/faker/providers/person/bg_BG/__init__.py
+++ b/faker/providers/person/bg_BG/__init__.py
@@ -1759,7 +1759,7 @@ class Provider(PersonProvider):
 
     formats_male = (
         "{{first_name_male}} {{last_name_male}}",
-        "{{prefix_female}} {{first_name_male}} {{last_name_male}}",
+        "{{prefix_male}} {{first_name_male}} {{last_name_male}}",
     )
 
     formats = formats_male + formats_female
diff --git a/faker/providers/person/uk_UA/__init__.py b/faker/providers/person/uk_UA/__init__.py
index 857c3f8e..56a785cf 100644
--- a/faker/providers/person/uk_UA/__init__.py
+++ b/faker/providers/person/uk_UA/__init__.py
@@ -1,26 +1,301 @@
 from collections import OrderedDict
+from typing import Dict, Optional
 
+from faker.typing import SexLiteral
+
+from .. import ElementsType
 from .. import Provider as PersonProvider
 
 
+def translit(text: str) -> str:
+    translit_dict: Dict[str, str] = {
+        "а": "a",
+        "б": "b",
+        "в": "v",
+        "г": "h",
+        "ґ": "g",
+        "д": "d",
+        "е": "e",
+        "є": "ie",
+        "ж": "zh",
+        "з": "z",
+        "и": "y",
+        "і": "i",
+        "ї": "i",
+        "й": "i",
+        "к": "k",
+        "л": "l",
+        "м": "m",
+        "н": "n",
+        "о": "o",
+        "п": "p",
+        "р": "r",
+        "с": "s",
+        "т": "t",
+        "у": "u",
+        "ф": "f",
+        "х": "kh",
+        "ц": "ts",
+        "ч": "ch",
+        "ш": "sh",
+        "щ": "shch",
+        "ь": "",
+        "ю": "iu",
+        "я": "ia",
+        "'": "",
+        "ʼ": "",
+        "-": "-",
+        "А": "A",
+        "Б": "B",
+        "В": "V",
+        "Г": "H",
+        "Ґ": "G",
+        "Д": "D",
+        "Е": "E",
+        "Є": "Ye",
+        "Ж": "Zh",
+        "З": "Z",
+        "И": "Y",
+        "І": "I",
+        "Ї": "Yi",
+        "Й": "Y",
+        "К": "K",
+        "Л": "L",
+        "М": "M",
+        "Н": "N",
+        "О": "O",
+        "П": "P",
+        "Р": "R",
+        "С": "S",
+        "Т": "T",
+        "У": "U",
+        "Ф": "F",
+        "Х": "Kh",
+        "Ц": "Ts",
+        "Ч": "Ch",
+        "Ш": "Sh",
+        "Щ": "Shch",
+        "Ь": "",
+        "Ю": "Yu",
+        "Я": "Ya",
+    }
+    for letter in text:
+        if letter.isalpha():
+            text = text.replace(letter, translit_dict[letter])
+    return text
+
+
 class Provider(PersonProvider):
     formats_female = OrderedDict(
         (
-            ("{{first_name_female}} {{last_name}}", 0.9),
+            ("{{first_name_female}} {{last_name}}", 0.8),
             ("{{prefix_female}} {{first_name_female}} {{last_name}}", 0.1),
+            ("{{last_name}} {{first_name_female}} {{middle_name_female}}", 0.1),
         )
     )
 
     formats_male = OrderedDict(
         (
-            ("{{first_name_male}} {{last_name}}", 0.9),
+            ("{{first_name_male}} {{last_name}}", 0.8),
             ("{{prefix_male}} {{first_name_male}} {{last_name}}", 0.1),
+            ("{{last_name}} {{first_name_male}} {{middle_name_male}}", 0.1),
         )
     )
 
     formats = formats_female.copy()
     formats.update(formats_male)
 
+    language_names: ElementsType[str] = [
+        "Афарська",
+        "Абхазька",
+        "Авестійська",
+        "Африкаанс",
+        "Акан (мова)",
+        "Амхара",
+        "Арагонська",
+        "Арабська",
+        "Ассамська",
+        "Аварська",
+        "Аймара",
+        "Азербайджанська",
+        "Башкирська",
+        "Білоруська",
+        "Болгарська",
+        "Біхарі",
+        "Біслама",
+        "Бамбара",
+        "Бенгальська",
+        "Тибетська",
+        "Бретонська",
+        "Боснійська",
+        "Каталонська",
+        "Чеченська",
+        "Себуанська",
+        "Чаморро",
+        "Корсиканська",
+        "Мова крі",
+        "Чеська",
+        "Церковнослов’янська",
+        "Чуваська",
+        "Валлійська",
+        "Данська",
+        "Німецька",
+        "Дівехі",
+        "Дзонґ-ке",
+        "Еве",
+        "Грецька",
+        "Англійська",
+        "Есперанто",
+        "Іспанська",
+        "Естонська",
+        "Баскська",
+        "Перська",
+        "Фула",
+        "Фінська",
+        "Фіджі",
+        "Фарерська",
+        "Французька",
+        "Західно-фризька",
+        "Ірландська",
+        "Шотландська гельська",
+        "Галісійська",
+        "Гуарані",
+        "Гуджараті",
+        "Менська",
+        "Хауса",
+        "Гавайська",
+        "Іврит",
+        "Гінді",
+        "Гірі-моту",
+        "Хорватська",
+        "Гаїтянська",
+        "Угорська",
+        "Вірменська",
+        "Гереро",
+        "Інтерлінгва",
+        "Індонезійська",
+        "Окциденталь",
+        "Ігбо",
+        "Сичуань Йї",
+        "Інупіак (мова)",
+        "Ідо",
+        "Ісландська",
+        "Італійська",
+        "Інуктітут",
+        "Японська",
+        "Яванська",
+        "Грузинська",
+        "Конголезька",
+        "Кікуйю",
+        "Кунама",
+        "Казахська",
+        "Гренландська",
+        "Кхмерська",
+        "Каннада",
+        "Корейська",
+        "Канурі",
+        "Кашмір",
+        "Курдська",
+        "Комі",
+        "Корнська",
+        "Киргизька",
+        "Латинська",
+        "Люксембурзька",
+        "Луганда",
+        "Лімбурзька",
+        "Лінґала",
+        "Лаоська",
+        "Литовська",
+        "Луба-катанга",
+        "Латиська",
+        "Малагасійська",
+        "Маршальська",
+        "Маорі",
+        "Македонська",
+        "Малаялам",
+        "Монгольська",
+        "Маратхі",
+        "Малайська",
+        "Мальтійська",
+        "Бірманська",
+        "Науру",
+        "Букмол",
+        "Північна ндебеле",
+        "Непальська",
+        "Ндонга",
+        "Нідерландська",
+        "Нюношк",
+        "Норвезька",
+        "Південна ндебеле",
+        "Навахо",
+        "Ньянджа",
+        "Окситанська",
+        "Оджибве",
+        "Орома",
+        "Орія",
+        "Осетинська",
+        "Панджабі",
+        "Палі",
+        "Польська",
+        "Пушту",
+        "Португальська",
+        "Кечуа",
+        "Ретороманська",
+        "Кірундійська",
+        "Румунська;Молдовська",
+        "Російська",
+        "Кінаруанда",
+        "Русинська",
+        "Санскрит",
+        "Сардинська",
+        "Сіндхі",
+        "Північносаамська",
+        "Санго",
+        "Сербохорватська",
+        "Сингальська",
+        "Словацька",
+        "Словенська",
+        "Самоанська",
+        "Шона",
+        "Сомалійська",
+        "Албанська",
+        "Сербська",
+        "Сваті",
+        "Сесото",
+        "Сунданська",
+        "Шведська",
+        "Суахілі",
+        "Тамільська",
+        "Телугу",
+        "Таджицька",
+        "Тайська",
+        "Тигрінья",
+        "Туркменська",
+        "Тагалог",
+        "Сетсвана",
+        "Тонганська",
+        "Турецька",
+        "Тсонґа",
+        "Татарська",
+        "Чві",
+        "Таїтянська",
+        "Уйгурська",
+        "Українська",
+        "Урду",
+        "Узбецька",
+        "Венда",
+        "В'єтнамська",
+        "Волапюк",
+        "Валлонська",
+        "Волоф",
+        "Коса",
+        "Їдиш",
+        "Йоруба",
+        "Чжуан",
+        "Китайська",
+        "Зулу",
+    ]
+
     # Source: uk.wikipedia.org/wiki/Українські_імена
     first_names_male = (
         "Аарон",
@@ -746,5 +1021,298 @@ class Provider(PersonProvider):
         "Ящук",
     )
 
-    prefixes_male = ("пан",)
-    prefixes_female = ("пані",)
+    middle_names_male = (
+        "Ааронович",
+        "Августинович",
+        "Аврелійович",
+        "Адамович",
+        "Азарович",
+        "Алевтинович",
+        "Альбертович",
+        "Амвросійович",
+        "Андрійович",
+        "Антонович",
+        "Аркадійович",
+        "Арсенович",
+        "Артемович",
+        "Орхипович",
+        "Богданович",
+        "Богодарович",
+        "Богуславович",
+        "Болеславович",
+        "Борисович",
+        "Бориславович",
+        "Вадимович",
+        "Валентинович",
+        "Валерійович",
+        "Варфоломійович",
+        "Васильович",
+        "Венедиктович",
+        "Веніяминович",
+        "Вікторович",
+        "Віталійович",
+        "Владиславович",
+        "Володимирович",
+        "Вʼячеславович",
+        "Гаврилович",
+        "Геннадійович",
+        "Георгійович",
+        "Гордійович",
+        "Григорійович",
+        "Глібович",
+        "Данилович",
+        "Давидович",
+        "Демидович",
+        "Демʼянович",
+        "Дмитрович",
+        "Захарович",
+        "Зиновійович",
+        "Зорянович",
+        "Іванович",
+        "Ігнатович",
+        "Ігорович",
+        "Едуардович",
+        "Євгенійович",
+        "Єлисейович",
+        "Єфремович",
+        "Йосипович",
+        "Климентович",
+        "Костянтинович",
+        "Леонідович",
+        "Леонтійович",
+        "Леопольдович",
+        "Лукʼянович",
+        "Кирилович",
+        "Макарович",
+        "Максимович",
+        "Мартинович",
+        "Микитович",
+        "Миколайович",
+        "Миронович",
+        "Мирославович",
+        "Михайлович",
+        "Назарович",
+        "Несторович",
+        "Олегович",
+        "Олексович",
+        "Олександрович",
+        "Олесьович",
+        "Омелянович",
+        "Опанасович",
+        "Орестович",
+        "Остапович",
+        "Охрімович",
+        "Петрович",
+        "Павлович",
+        "Панасович",
+        "Пантелеймонович",
+        "Пилипович",
+        "Прохорович",
+        "Романович",
+        "Ростиславович",
+        "Русланович",
+        "Святославович",
+        "Семенович",
+        "Сергійович",
+        "Симонович",
+        "Соломонович",
+        "Станіславович",
+        "Степанович",
+        "Стефанович",
+        "Тарасович",
+        "Теодорович",
+        "Тимофійович",
+        "Трохимович",
+        "Устимович",
+        "Федорович",
+        "Хомович",
+        "Юстимович",
+        "Юхимович",
+        "Яковович",
+        "Яремович",
+        "Ярославович",
+    )
+    middle_names_female = (
+        "Ааронівна",
+        "Августинівна",
+        "Аврелійовна",
+        "Адамівна",
+        "Азарівна",
+        "Алевтинівна",
+        "Альбертівна",
+        "Амвросійовна",
+        "Андріївна",
+        "Антонівна",
+        "Аркадіївна",
+        "Арсенівна",
+        "Артемівна",
+        "Орхипівна",
+        "Богданівна",
+        "Богодарівна",
+        "Богуславівна",
+        "Болеславівна",
+        "Борисівна",
+        "Бориславівна",
+        "Вадимівна",
+        "Валентинівна",
+        "Валеріївна",
+        "Варфоломіївна",
+        "Васильівна",
+        "Венедиктівна",
+        "Веніяминівна",
+        "Вікторівна",
+        "Віталіївна",
+        "Владиславівна",
+        "Володимирівна",
+        "Вʼячеславівна",
+        "Гаврилівна",
+        "Геннадіївна",
+        "Георгіївна",
+        "Германівна",
+        "Гордіївна",
+        "Григоріївна",
+        "Глібівна",
+        "Данилівна",
+        "Давидівна",
+        "Данівна",
+        "Демидівна",
+        "Демʼянівна",
+        "Дмитріївна",
+        "Захарівна",
+        "Зорянівна",
+        "Іванівна",
+        "Ігнатівна",
+        "Ігорівна",
+        "Іллівна",
+        "Едуардівна",
+        "Євгенівна",
+        "Єлисеївна",
+        "Єфремівна",
+        "Йосипівна",
+        "Климентівна",
+        "Костянтинівна",
+        "Лесівна",
+        "Леонідівна",
+        "Леонтіївна",
+        "Леопольдівна",
+        "Лукʼянівна",
+        "Кирилівна",
+        "Макарівна",
+        "Максимівна",
+        "Марківна",
+        "Мартинівна",
+        "Микитівна",
+        "Миколаївна",
+        "Миронівна",
+        "Мирославівна",
+        "Михайлівна",
+        "Назарівна",
+        "Несторівна",
+        "Олегівна",
+        "Олександрівна",
+        "Омелянівна",
+        "Опанасівна",
+        "Орестівна",
+        "Остапівна",
+        "Охрімівна",
+        "Петрівна",
+        "Павлівна",
+        "Панасівна",
+        "Пантелеймонівна",
+        "Пилипівна",
+        "Прохорівна",
+        "Романівна",
+        "Ростиславівна",
+        "Русланівна",
+        "Святославівна",
+        "Семенівна",
+        "Сергіївна",
+        "Симонівна",
+        "Соломонівна",
+        "Спасівна",
+        "Станіславівна",
+        "Степанівна",
+        "Стефанівна",
+        "Тарасівна",
+        "Теодорівна",
+        "Тимофіївна",
+        "Трохимівна",
+        "Устимівна",
+        "Федорівна",
+        "Феофанівна",
+        "Францівна",
+        "Юстимівна",
+        "Юхимівна",
+        "Яремівна",
+        "Ярославівна",
+    )
+    middle_names = middle_names_male + middle_names_female
+
+    prefixes_male = OrderedDict(
+        (
+            ("пан", 0.8),
+            ("добродій", 0.2),
+        )
+    )
+
+    prefixes_female = OrderedDict(
+        (
+            ("пані", 0.8),
+            ("панна", 0.1),
+            ("добродійка", 0.1),
+        )
+    )
+
+    def middle_name(self) -> str:
+        """
+        Generate random middle name.
+        :sample:
+        """
+        return self.random_element(self.middle_names)
+
+    def middle_name_male(self) -> str:
+        """
+        Generate random male middle name.
+        :sample:
+        """
+        return self.random_element(self.middle_names_male)
+
+    def middle_name_female(self) -> str:
+        """
+        Generate random female middle name.
+        :sample:
+        """
+        return self.random_element(self.middle_names_female)
+
+    def full_name(self, gender: Optional[SexLiteral] = None, short: Optional[bool] = False) -> str:
+        """
+        Generate Full Name
+            - gender = 'M' or 'F' optional params
+            - short: bool optional params. default is False
+
+        :example: 'Петриченко Петро Сергійович'
+        :example: 'Петриченко П.С.'
+
+        :sample:
+        :sample: gender='F'
+        :sample: gender='M'
+        :sample: short=True
+        """
+        if gender and gender not in ("M", "F"):
+            raise ValueError('Gender must be "m" or "f" or None')
+
+        gender_ = gender if gender else self.random_element(elements=["M", "F"])
+
+        if gender_ == "M":
+            first_name = self.first_name_male()
+            last_name = self.last_name_male()
+            middle_name = self.middle_name_male()
+        else:
+            first_name = self.first_name_female()
+            last_name = self.last_name_female()
+            middle_name = self.middle_name_female()
+
+        if short:
+            return f"{last_name} {first_name[0]}.{middle_name[0]}."
+
+        return f"{last_name} {first_name} {middle_name}"
diff --git a/faker/providers/phone_number/nl_BE/__init__.py b/faker/providers/phone_number/nl_BE/__init__.py
index 3b62626d..d02c4fa5 100644
--- a/faker/providers/phone_number/nl_BE/__init__.py
+++ b/faker/providers/phone_number/nl_BE/__init__.py
@@ -19,4 +19,6 @@ class Provider(PhoneNumberProvider):
         "+32(0)##-#######",
         "(0###)-######",
         "(0##)-#######",
+        "0#/ ### ## ##",
+        "0# ### ## ##"
     )


Test patch:
diff --git a/tests/providers/test_address.py b/tests/providers/test_address.py
index fa8ebf29..45607994 100644
--- a/tests/providers/test_address.py
+++ b/tests/providers/test_address.py
@@ -2159,6 +2159,26 @@ class TestHuHu:
             match = re.fullmatch(r"\d{0,3}.", building_number)
             assert match
 
+    def test_city(self, faker, num_samples):
+        # generating possible variations for cities for hu_Hu locale
+        real_cities = [city.lower() for city in HuHuAddressProvider.real_city_names]
+        cities_part_suffix = [
+            "".join([part, suffix])
+            for part in HuHuAddressProvider.city_parts
+            for suffix in HuHuAddressProvider.city_suffixes
+        ]
+        cities_prefix_part_suffix = [
+            "".join([pref, part_suffix])
+            for pref in HuHuAddressProvider.city_prefs
+            for part_suffix in cities_part_suffix
+        ]
+        cities = real_cities + cities_part_suffix + cities_prefix_part_suffix
+        for _ in range(num_samples):
+            city = faker.city()
+            assert isinstance(city, str)
+            assert city.lower() in cities
+            assert city[0].isupper()
+
 
 class TestIdId:
     """Test id_ID address provider methods"""
diff --git a/tests/providers/test_credit_card.py b/tests/providers/test_credit_card.py
index 6cd37934..2049b1a7 100644
--- a/tests/providers/test_credit_card.py
+++ b/tests/providers/test_credit_card.py
@@ -3,6 +3,7 @@ import re
 from typing import Pattern
 
 from faker.providers.bank.ru_RU import Provider as RuRuBankProvider
+from faker.providers.bank.uk_UA import Provider as UkUaBankProvider
 from faker.providers.credit_card import Provider as CreditCardProvider
 
 
@@ -152,3 +153,39 @@ class TestPtPt:
         for _ in range(num_samples):
             number = faker.credit_card_number("maestro")
             assert self.maestro_pattern.fullmatch(number)
+
+
+class TestUkUa:
+    mastercard_pattern: Pattern = re.compile(
+        r"(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}",
+    )
+    visa_pattern: Pattern = re.compile(r"4[0-9]{12}([0-9]{3}){0,2}")
+    maestro_pattern: Pattern = re.compile(r"(67)[0-9]{14}")
+    prostir_pattern: Pattern = re.compile(r"(9)[0-9]{15}")
+
+    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_visa(self, faker, num_samples):
+        for _ in range(num_samples):
+            number = faker.credit_card_number("visa")
+            assert self.visa_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)
+
+    def test_prostir(self, faker, num_samples):
+        for _ in range(num_samples):
+            number = faker.credit_card_number("prostir")
+            assert self.prostir_pattern.fullmatch(number)
+
+    def test_credit_card_full(self, faker, num_samples):
+        for _ in range(num_samples):
+            card_data = faker.credit_card_full("prostir").split("\n")
+            assert re.match("[A-Za-z]+", card_data[1])
+            assert card_data[4] in UkUaBankProvider.banks
+            assert card_data[0] == "ПРОСТІР"
diff --git a/tests/providers/test_person.py b/tests/providers/test_person.py
index 8112da58..19ca4a6f 100644
--- a/tests/providers/test_person.py
+++ b/tests/providers/test_person.py
@@ -34,6 +34,8 @@ from faker.providers.person.sk_SK import Provider as SkSKProvider
 from faker.providers.person.sv_SE import Provider as SvSEProvider
 from faker.providers.person.ta_IN import Provider as TaINProvider
 from faker.providers.person.th_TH import Provider as ThThProvider
+from faker.providers.person.uk_UA import Provider as UkUAProvider
+from faker.providers.person.uk_UA import translit as UkUATranslit
 from faker.providers.person.zh_CN import Provider as ZhCNProvider
 from faker.providers.person.zh_TW import Provider as ZhTWProvider
 from faker.providers.person.zu_ZA import Provider as ZuZAProvider
@@ -1474,5 +1476,73 @@ class TestZuZa(unittest.TestCase):
             raise AssertionError("Invalid number of name parts. Expected 2 or 3.")
 
 
+class TestUkUa(unittest.TestCase):
+    def setUp(self):
+        self.fake = Faker("uk_UA")
+        Faker.seed(0)
+        self.provider = UkUAProvider
+        self.translit = UkUATranslit
+
+    def test_middle_names(self):
+        for _ in range(100):
+            res = self.fake.middle_name()
+            assert res in self.provider.middle_names
+
+    def test_male_middle_names(self):
+        for _ in range(100):
+            res = self.fake.middle_name_male()
+            assert res in self.provider.middle_names_male
+
+    def test_female_middle_names(self):
+        for _ in range(100):
+            res = self.fake.middle_name_female()
+            assert res in self.provider.middle_names_female
+
+    def test_language_name(self):
+        for _ in range(100):
+            language_name = self.fake.language_name()
+            assert language_name in self.provider.language_names
+
+    def test_transliteration(self):
+        assert self.translit("Сергій") == "Serhii"
+        assert self.translit("Лілія") == "Liliia"
+        assert self.translit("Яся") == "Yasia"
+        assert self.translit("Демʼян") == "Demian"
+        assert self.translit("Марʼяна") == "Mariana"
+        assert (
+            self.translit("абвгґдеєжзиіїйклмнопрстуфхцчшщьюяєʼ'-") == "abvhgdeiezhzyiiiklmnoprstufkhtschshshchiuiaie'-"
+        )
+        assert self.translit("АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ") == "ABVHGDEYeZhZYIYiYKLMNOPRSTUFKhTsChShShchYuYa"
+
+    def test_full_name_male(self):
+        for _ in range(10):
+            res = self.fake.full_name(gender="M")
+            last_name, first_name, middle_name = res.split(" ")
+            assert last_name in self.provider.last_names
+            assert first_name in self.provider.first_names_male
+            assert middle_name in self.provider.middle_names_male
+
+    def test_full_name_female(self):
+        for _ in range(10):
+            res = self.fake.full_name(gender="F")
+            last_name, first_name, middle_name = res.split(" ")
+            assert last_name in self.provider.last_names
+            assert first_name in self.provider.first_names_female
+            assert middle_name in self.provider.middle_names_female
+
+    def test_full_name(self):
+        for _ in range(10):
+            res = self.fake.full_name()
+            last_name, first_name, middle_name = res.split(" ")
+            assert last_name in self.provider.last_names
+            assert first_name in self.provider.first_names
+            assert middle_name in self.provider.middle_names
+
+    def test_short_full_name(self):
+        res = self.fake.full_name(short=True)
+        assert res.count(".") == 2
+        assert res.count(" ") == 1
+
+
 if __name__ == "__main__":
     unittest.main()