diff --git a/faker/providers/address/mk_MK/__init__.py b/faker/providers/address/mk_MK/__init__.py new file mode 100644 index 0000000000..13d738c053 --- /dev/null +++ b/faker/providers/address/mk_MK/__init__.py @@ -0,0 +1,380 @@ +from .. import Provider as AddressProvider + + +class Provider(AddressProvider): + """Address provider for mk_MK locale (Macedonian). + + Sources: + - https://en.wikipedia.org/wiki/List_of_cities_in_North_Macedonia + - https://en.wikipedia.org/wiki/List_of_sovereign_states + """ + + city_formats = ("{{city_name}}",) + + street_name_formats = ("{{street_name}}",) + street_address_formats = ("{{street_name}} {{building_number}}",) + address_formats = ("{{street_address}}\n{{postcode}} {{city}}",) + + building_number_formats = ( + "###", + "##", + "#", + "#а", + "#б", + "#в", + "#а/#", + "#б/#", + ) + + postcode_formats = ("#####",) + + street_suffixes_long = ( + "", + "улица", + "булевар", + "пат", + "авенија", + ) + + street_suffixes_short = ( + "", + "ул.", + "бул.", + "п.", + "а.", + ) + + cities = ( + "Берово", # Berovo + "Битола", # Bitola + "Богданци", # Bogdanci + "Валандово", # Valandovo + "Велес", # Veles + "Виница", # Vinica + "Гевгелија", # Gevgelija + "Гостивар", # Gostivar + "Дебар", # Debar + "Делчево", # Delčevo + "Демир Капија", # Demir Kapija + "Демир Хисар", # Demir Hisar + "Кавадарци", # Kavadarci + "Кичево", # Kičevo + "Кочани", # Kočani + "Кратово", # Kratovo + "Крива Паланка", # Kriva Palanka + "Крушево", # Kruševo + "Куманово", # Kumanovo + "Македонска Каменица", # Makedonska Kamenica + "Македонски Брод", # Makedonski Brod + "Неготино", # Negotino + "Охрид", # Ohrid + "Пехчево", # Pehčevo + "Прилеп", # Prilep + "Пробиштип", # Probištip + "Радовиш", # Radoviš + "Ресен", # Resen + "Свети Николе", # Sveti Nikole + "Скопје", # Skopje + "Струга", # Struga + "Струмица", # Strumica + "Тетово", # Tetovo + "Штип", # Štip + ) + + # Source: OpenStreetMap Overpass API — named roads in Скопје + streets = ( + "Македонија", + "Партизански одреди", + "Илинденска", + "Димитар Влахов", + "Кеј Димитар Влахов", + "Кеј Македонија", + "Орце Николов", + "Никола Карев", + "Климент Охридски", + "Крсте Мисирков", + "Гоце Делчев", + "Даме Груев", + "Јане Сандански", + "Христијан Тодоровски Карпош", + "Питу Гули", + "Тодор Александров", + "Свети Климент Охридски", + "Благој Давков", + "Наум Охридски", + "Булевар Александар Македонски", + "Булевар Блаже Конески", + "Булевар Гоце Делчев", + "Булевар Никола Карев", + "Булевар Партизански одреди", + "Булевар Свети Климент Охридски", + "Булевар Цветан Димов", + "Самоилова", + "Глигор Прличев", + "Ибрахим Темо", + "Васил Главинов", + "Никола Вапцаров", + "Маршал Тито", + "Едвард Кардељ", + "Георги Димитров", + "Михаило Апостолски", + "Михаило Пупин", + "Перо Наков", + "Петар Поп Арсов", + "Јован Хаџи Константинов Џинот", + "Кирил Пејчиновиќ", + "Лазар Личеноски", + "Никола Русински", + "Аристотел", + "Луј Пастер", + "Николај Коперник", + "Стоби", + "Скупи", + "Дојранска", + "Воденска", + "Софиска", + "Варшавска", + "Виенска", + "Женевска", + "Лондонска", + "Букурешка", + "Будимпештанска", + "Хелсинки", + "Бриселска", + "Ленинградска", + "Волгоградска", + "Крушевска", + "Радовишка", + "Трета македонска бригада", + "Пролетерска", + "Востаничка", + "Одбранбена", + "Зелезничка", + "Рибарска", + "Јасминска", + "Природна", + "Шарпланинска", + "Славеј Планина", + ) + + states = ( + "Скопски", + "Пелагониски", + "Полошки", + "Вардарски", + "Источен", + "Западен", + "Југозападен", + "Југоисточен", + "Североисточен", + "Централен", + ) + + countries = ( + "Авганистан", + "Австралија", + "Австрија", + "Азербејџан", + "Албанија", + "Алжир", + "Андора", + "Ангола", + "Антигва и Барбуда", + "Аргентина", + "Ерменија", + "Бахами", + "Бахреин", + "Бангладеш", + "Барбадос", + "Белорусија", + "Белгија", + "Белизе", + "Бенин", + "Бутан", + "Боливија", + "Босна и Херцеговина", + "Боцвана", + "Бразил", + "Брунеј", + "Бугарија", + "Буркина Фасо", + "Бурунди", + "Кабо Верде", + "Камбоџа", + "Камерун", + "Канада", + "Централноафриканска Република", + "Чад", + "Чиле", + "Кина", + "Колумбија", + "Коморски Острови", + "Демократска Република Конго", + "Република Конго", + "Коста Рика", + "Кот д'Ивоар", + "Хрватска", + "Куба", + "Кипар", + "Чешка", + "Данска", + "Џибути", + "Доминика", + "Доминиканска Република", + "Источен Тимор", + "Еквадор", + "Египет", + "Ел Салвадор", + "Екваторска Гвинеја", + "Еритреја", + "Естонија", + "Есватини", + "Етиопија", + "Фиџи", + "Финска", + "Франција", + "Габон", + "Гамбија", + "Грузија", + "Германија", + "Гана", + "Грција", + "Гренада", + "Гватемала", + "Гвинеја", + "Гвинеја Бисао", + "Гајана", + "Хаити", + "Хондурас", + "Унгарија", + "Исланд", + "Индија", + "Индонезија", + "Иран", + "Ирак", + "Ирска", + "Израел", + "Италија", + "Јамајка", + "Јапонија", + "Јордан", + "Казахстан", + "Кенија", + "Кирибати", + "Северна Кореја", + "Јужна Кореја", + "Косово", + "Кувајт", + "Киргистан", + "Лаос", + "Латвија", + "Либан", + "Лесото", + "Либерија", + "Либија", + "Лихтенштајн", + "Литванија", + "Луксембург", + "Мадагаскар", + "Малави", + "Малезија", + "Малдиви", + "Мали", + "Малта", + "Маршалски Острови", + "Мавританија", + "Маврициус", + "Мексико", + "Микронезија", + "Молдавија", + "Монако", + "Монголија", + "Черна Гора", + "Мароко", + "Мозамбик", + "Мјанмар", + "Намибија", + "Науру", + "Непал", + "Холандија", + "Нов Зеланд", + "Никарагва", + "Нигер", + "Нигерија", + "Северна Македонија", + "Норвешка", + "Оман", + "Пакистан", + "Палау", + "Панама", + "Папуа Нова Гвинеја", + "Парагвај", + "Перу", + "Филипини", + "Полска", + "Португалија", + "Катар", + "Романија", + "Русија", + "Руанда", + "Сент Китс и Невис", + "Света Луција", + "Сент Винсент и Гренадини", + "Самоа", + "Сан Марино", + "Саудиска Арабија", + "Сенегал", + "Србија", + "Сејшели", + "Сиера Леоне", + "Сингапур", + "Словачка", + "Словенија", + "Соломонски Острови", + "Сомалија", + "Јужна Африка", + "Јужен Судан", + "Шпанија", + "Шри Ланка", + "Судан", + "Суринам", + "Шведска", + "Швајцарија", + "Сирија", + "Тајван", + "Таџикистан", + "Танзанија", + "Тајланд", + "Того", + "Тонга", + "Тринидад и Тобаго", + "Тунис", + "Турција", + "Туркменистан", + "Тувалу", + "Уганда", + "Украина", + "Обединети Арапски Емирати", + "Обединето Кралство", + "Соединети Американски Држави", + "Уругвај", + "Узбекистан", + "Вануату", + "Ватикан", + "Венецуела", + "Виетнам", + "Јемен", + "Замбија", + "Зимбабве", + ) + + def city_name(self) -> str: + return self.random_element(self.cities) + + def street_name(self) -> str: + return self.random_element(self.streets) + + def administrative_unit(self) -> str: + return self.random_element(self.states) + + state = administrative_unit diff --git a/faker/providers/automotive/mk_MK/__init__.py b/faker/providers/automotive/mk_MK/__init__.py new file mode 100644 index 0000000000..5316cc377c --- /dev/null +++ b/faker/providers/automotive/mk_MK/__init__.py @@ -0,0 +1,66 @@ +from .. import Provider as AutomotiveProvider + + +class Provider(AutomotiveProvider): + """Automotive provider for mk_MK locale (Macedonian). + + Sources: + - https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_North_Macedonia + + Standard format: XX NNNN YY + where XX = two-letter regional code, NNNN = 4-digit number, YY = two letters + + Notes: + - Letters Q, W, X, Y are NOT used (no Cyrillic equivalents). + - Country identifier changed from MK to NMK in February 2019 (Prespa Agreement). + """ + + # All 34 official regional codes as of 2020 + # Sources: original 1993 codes + expansions in 2012, 2013, 2015, 2019, 2020 + license_plate_prefixes = ( + "BE", # Berovo + "BT", # Bitola + "DB", # Debar + "DE", # Delčevo + "DH", # Demir Hisar + "DK", # Demir Kapija + "GE", # Gevgelija + "GV", # Gostivar + "KA", # Kavadarci + "KI", # Kičevo + "KO", # Kočani + "KP", # Kriva Palanka + "KR", # Kratovo + "KS", # Kruševo + "KU", # Kumanovo + "MB", # Makedonski Brod + "MK", # Makedonska Kamenica (municipality) + "NE", # Negotino + "OH", # Ohrid + "PE", # Pehčevo + "PP", # Prilep + "PS", # Probištip + "RA", # Radoviš + "RE", # Resen + "SK", # Skopje + "SN", # Sveti Nikole + "SR", # Strumica + "ST", # Štip + "SU", # Struga + "TE", # Tetovo + "VA", # Valandovo + "VE", # Veles + "VI", # Vinica + "VV", # Vevčani + ) + + # Latin letters used on plates — Q, W, X, Y are excluded (no Cyrillic equivalents) + license_plate_suffix_letters = "ABCDEFGHIJKLMNOPRSTUVZ" + + def license_plate(self) -> str: + prefix = self.random_element(self.license_plate_prefixes) + number = self.numerify("####") + suffix = self.random_element( + self.license_plate_suffix_letters + ) + self.random_element(self.license_plate_suffix_letters) + return f"{prefix} {number} {suffix}" diff --git a/faker/providers/bank/mk_MK/__init__.py b/faker/providers/bank/mk_MK/__init__.py new file mode 100644 index 0000000000..dea550cd1f --- /dev/null +++ b/faker/providers/bank/mk_MK/__init__.py @@ -0,0 +1,32 @@ +from .. import Provider as BankProvider + + +class Provider(BankProvider): + """Bank provider for mk_MK locale (Macedonian). + + Sources: + - https://en.wikipedia.org/wiki/IBAN#IBAN_formats_by_country + MK IBAN: MK + 2 check digits + 3-digit bank code + 10-digit account + 2 national check digits + Total BBAN length: 15 digits/chars (3 bank + 10 account + 2 check) + - https://en.wikipedia.org/wiki/List_of_banks_in_North_Macedonia + """ + + bban_format = "###????????????##" + country_code = "MK" + + banks = ( + "Народна банка на Република Северна Македонија", + "Силк Роуд банка", + "Халк банка", + "Шпаркасе банка", + "Капитал банка", + "Комерцијална банка", + "Развојна банка на Северна Македонија", + "НЛБ банка", + "ПроКредит банка", + "Централна кооперативна банка", + "Алта банка", + "Стопанска банка", + "Универзална инвестициона банка", + "ТТК банка", + ) diff --git a/faker/providers/color/mk_MK/__init__.py b/faker/providers/color/mk_MK/__init__.py new file mode 100644 index 0000000000..da2e42dec8 --- /dev/null +++ b/faker/providers/color/mk_MK/__init__.py @@ -0,0 +1,75 @@ +from collections import OrderedDict + +from .. import Provider as ColorProvider + +localized = True + + +class Provider(ColorProvider): + """Color provider for mk_MK locale (Macedonian). + + Sources: + - https://mk.wikipedia.org/wiki/Боја (spectrum colors with hex codes) + - Standard Macedonian color terminology with CSS/web hex values + """ + + all_colors = OrderedDict( + ( + ("Црвена", "#FF0000"), + ("Портокалова", "#FF6600"), + ("Жолта", "#FFFF00"), + ("Зелена", "#008000"), + ("Сина", "#0000FF"), + ("Виолетова", "#8000FF"), + ("Бела", "#FFFFFF"), + ("Црна", "#000000"), + ("Сива", "#808080"), + ("Кафеава", "#8B4513"), + ("Розова", "#FFC0CB"), + ("Тиркизна", "#40E0D0"), + ("Кармин", "#DC143C"), + ("Лимонова", "#FFF44F"), + ("Маслинова", "#808000"), + ("Темноцрвена", "#8B0000"), + ("Темносина", "#00008B"), + ("Темнозелена", "#006400"), + ("Светлосина", "#ADD8E6"), + ("Светлозелена", "#90EE90"), + ("Светлосива", "#D3D3D3"), + ("Темносива", "#A9A9A9"), + ("Сребрена", "#C0C0C0"), + ("Златна", "#FFD700"), + ("Бронзена", "#CD7F32"), + ("Индиго", "#4B0082"), + ("Лавандула", "#E6E6FA"), + ("Корал", "#FF7F50"), + ("Лосос", "#FA8072"), + ("Магента", "#FF00FF"), + ("Цијан", "#00FFFF"), + ("Мастилена", "#000080"), + ("Бордо", "#800020"), + ("Бежова", "#F5F5DC"), + ("Теракота", "#E2725B"), + ("Охра", "#CC7722"), + ("Слонова коска", "#FFFFF0"), + ("Нане", "#98FF98"), + ("Рубин", "#9B111E"), + ("Смарагдна", "#50C878"), + ("Аквамарин", "#7FFFD4"), + ("Чоколадова", "#D2691E"), + ) + ) + + safe_colors = ( + "црна", + "кестенлива", + "зелена", + "маслинова", + "виолетова", + "цијан", + "сина", + "сребрена", + "сива", + "жолта", + "бела", + ) diff --git a/faker/providers/company/mk_MK/__init__.py b/faker/providers/company/mk_MK/__init__.py new file mode 100644 index 0000000000..a9f7806873 --- /dev/null +++ b/faker/providers/company/mk_MK/__init__.py @@ -0,0 +1,23 @@ +from .. import Provider as CompanyProvider + + +class Provider(CompanyProvider): + """Company provider for mk_MK locale (Macedonian).""" + + formats = ( + "{{last_name}} {{company_suffix}}", + "{{last_name}} {{last_name}} {{company_suffix}}", + "{{last_name}}", + "{{last_name}} и {{last_name}} {{company_suffix}}", + ) + + company_suffixes = ( + "АД", + "ДОО", + "ДООЕЛ", + "ЕД", + "КД", + "ТД", + "ЈП", + "ООД", + ) diff --git a/faker/providers/currency/mk_MK/__init__.py b/faker/providers/currency/mk_MK/__init__.py new file mode 100644 index 0000000000..817ff6bf9b --- /dev/null +++ b/faker/providers/currency/mk_MK/__init__.py @@ -0,0 +1,162 @@ +from .. import Provider as CurrencyProvider + + +class Provider(CurrencyProvider): + """Currency provider for mk_MK locale (Macedonian). + + Sources: + - https://mk.wikipedia.org/wiki/Валута + - https://en.wikipedia.org/wiki/List_of_circulating_currencies + """ + + # Currency names in Macedonian + currencies = ( + ("AED", "Дирхам на ОАЕ"), + ("AFN", "Авганистански авганија"), + ("ALL", "Албански лек"), + ("AMD", "Ерменски драм"), + ("ANG", "Нидерландски антилски гулден"), + ("AOA", "Анголска кванза"), + ("ARS", "Аргентинско пезо"), + ("AUD", "Австралиски долар"), + ("AWG", "Арубански флорин"), + ("AZN", "Азербејџански манат"), + ("BAM", "Конвертибилна марка на БиХ"), + ("BBD", "Барбадоски долар"), + ("BDT", "Бангладешка така"), + ("BGN", "Бугарски лев"), + ("BHD", "Бахреински динар"), + ("BIF", "Бурундиски франк"), + ("BMD", "Бермудски долар"), + ("BND", "Брунејски долар"), + ("BOB", "Боливиско боливијано"), + ("BRL", "Бразилски реал"), + ("BSD", "Бахамски долар"), + ("BTN", "Бутански нгултрум"), + ("BWP", "Ботсванска пула"), + ("BYN", "Белоруска рубља"), + ("BZD", "Белиски долар"), + ("CAD", "Канадски долар"), + ("CDF", "Конгоански франк"), + ("CHF", "Швајцарски франк"), + ("CLP", "Чилеанско пезо"), + ("CNY", "Кинески јуан"), + ("COP", "Колумбиско пезо"), + ("CRC", "Костариканска колона"), + ("CUP", "Кубанско пезо"), + ("CVE", "Кабовердско ескудо"), + ("CZK", "Чешка круна"), + ("DJF", "Џибутиски франк"), + ("DKK", "Данска круна"), + ("DOP", "Доминиканско пезо"), + ("DZD", "Алжирски динар"), + ("EGP", "Египетска фунта"), + ("ERN", "Еритрејска накфа"), + ("ETB", "Етиопски бир"), + ("EUR", "Евро"), + ("FJD", "Фиџиски долар"), + ("GBP", "Британска фунта"), + ("GEL", "Грузиски лари"), + ("GHS", "Гански седи"), + ("GMD", "Гамбиски даласи"), + ("GNF", "Гвинејски франк"), + ("GTQ", "Гватемалски кецал"), + ("GYD", "Гвајански долар"), + ("HKD", "Хонгконшки долар"), + ("HNL", "Хондураска лемпира"), + ("HTG", "Хаитски гурд"), + ("HUF", "Унгарски форинт"), + ("IDR", "Индонезиска рупија"), + ("ILS", "Израелски нов шекел"), + ("INR", "Индиска рупија"), + ("IQD", "Ирачки динар"), + ("IRR", "Ирански риал"), + ("ISK", "Исландска круна"), + ("JMD", "Јамајски долар"), + ("JOD", "Јорданоски динар"), + ("JPY", "Јапонски јен"), + ("KES", "Кенијски шилинг"), + ("KGS", "Киргистански сом"), + ("KHR", "Камбоџански риел"), + ("KMF", "Коморски франк"), + ("KPW", "Северна корејска вона"), + ("KRW", "Јужна корејска вона"), + ("KWD", "Кувајтски динар"), + ("KZT", "Казахстански тенге"), + ("LAK", "Лаоски кип"), + ("LBP", "Либанска фунта"), + ("LKR", "Шриланканска рупија"), + ("LRD", "Либериски долар"), + ("LYD", "Либиски динар"), + ("MAD", "Марокански дирхам"), + ("MDL", "Молдавски леу"), + ("MGA", "Малагасиски ариари"), + ("MKD", "Македонски денар"), + ("MMK", "Мјанмарски кјат"), + ("MNT", "Монголски тугрик"), + ("MUR", "Маурициска рупија"), + ("MVR", "Малдивска руфија"), + ("MWK", "Малависка квача"), + ("MXN", "Мексиканско пезо"), + ("MYR", "Малезиски рингит"), + ("MZN", "Мозамбичка метикала"), + ("NAD", "Намибиски долар"), + ("NGN", "Нигериска најра"), + ("NIO", "Никарагванска кордоба"), + ("NOK", "Норвешка круна"), + ("NPR", "Непалска рупија"), + ("NZD", "Новозеландски долар"), + ("OMR", "Оманскт риал"), + ("PAB", "Панамска балбоа"), + ("PEN", "Перуански сол"), + ("PHP", "Филипинско пезо"), + ("PKR", "Пакистанска рупија"), + ("PLN", "Полски злоти"), + ("PYG", "Парагвајски гварани"), + ("QAR", "Катарски риал"), + ("RON", "Романски леу"), + ("RSD", "Српски динар"), + ("RUB", "Руска рубља"), + ("RWF", "Руандски франк"), + ("SAR", "Саудиски ријал"), + ("SBD", "Доларот на Соломоновите Острови"), + ("SCR", "Сејшелска рупија"), + ("SDG", "Судански фунт"), + ("SEK", "Шведска круна"), + ("SGD", "Сингапурски долар"), + ("SLL", "Сиера Леонски леоне"), + ("SOS", "Сомалиски шилинг"), + ("SRD", "Суринамски долар"), + ("SYP", "Сириска фунта"), + ("SZL", "Свазиленд лилангени"), + ("THB", "Тајландски бат"), + ("TJS", "Таџикистански сомони"), + ("TMT", "Туркменистански манат"), + ("TND", "Тунизиски динар"), + ("TRY", "Турска лира"), + ("TTD", "Тринидадски долар"), + ("TWD", "Нов тајвански долар"), + ("TZS", "Танзаниски шилинг"), + ("UAH", "Украинска хривна"), + ("UGX", "Угандиски шилинг"), + ("USD", "Американски долар"), + ("UYU", "Уругвајско пезо"), + ("UZS", "Узбекистански сум"), + ("VES", "Венецуелански боливар"), + ("VND", "Виетнамски донг"), + ("VUV", "Вануатски вату"), + ("WST", "Самоанска тала"), + ("XAF", "Централноафрикански франк CFA"), + ("XCD", "Источнокарипски долар"), + ("XOF", "Западноафрикански франк CFA"), + ("XPF", "Франк CFP"), + ("YER", "Јеменски риал"), + ("ZAR", "Јужноафрикански ренд"), + ("ZMW", "Замбиска квача"), + ("ZWL", "Зимбабвески долар"), + ) + + price_formats = ("# ден.", "## ден.", "### ден.", "#.### ден.", "##.### ден.") + + def pricetag(self) -> str: + return self.numerify(self.random_element(self.price_formats)) diff --git a/faker/providers/date_time/mk_MK/__init__.py b/faker/providers/date_time/mk_MK/__init__.py new file mode 100644 index 0000000000..aad67b206d --- /dev/null +++ b/faker/providers/date_time/mk_MK/__init__.py @@ -0,0 +1,38 @@ +from .. import Provider as DateTimeProvider + + +class Provider(DateTimeProvider): + """Date/time provider for mk_MK locale (Macedonian).""" + + # Days of week in Macedonian + DAY_NAMES = { + "0": "Понеделник", + "1": "Вторник", + "2": "Среда", + "3": "Четврток", + "4": "Петок", + "5": "Сабота", + "6": "Недела", + } + + # Months in Macedonian + MONTH_NAMES = { + "01": "Јануари", + "02": "Февруари", + "03": "Март", + "04": "Април", + "05": "Мај", + "06": "Јуни", + "07": "Јули", + "08": "Август", + "09": "Септември", + "10": "Октомври", + "11": "Ноември", + "12": "Декември", + } + + def day_of_week(self) -> str: + return self.DAY_NAMES[self.date("%w")] + + def month_name(self) -> str: + return self.MONTH_NAMES[self.month()] diff --git a/faker/providers/geo/mk_MK/__init__.py b/faker/providers/geo/mk_MK/__init__.py new file mode 100644 index 0000000000..86612969f4 --- /dev/null +++ b/faker/providers/geo/mk_MK/__init__.py @@ -0,0 +1,21 @@ +from decimal import Decimal + +from .. import Provider as GeoProvider + + +class Provider(GeoProvider): + """Geo provider for mk_MK locale (Macedonian). + + Sources: + - https://en.wikipedia.org/wiki/Geography_of_North_Macedonia + Bounding box: lat 40.85°N – 42.37°N, lon 20.45°E – 23.03°E + Center (Skopje): lat 41.9981°N, lon 21.4254°E + """ + + def local_latitude(self) -> Decimal: + """Return a latitude within North Macedonia's bounding box.""" + return self.coordinate(center=41.6, radius=0.75) + + def local_longitude(self) -> Decimal: + """Return a longitude within North Macedonia's bounding box.""" + return self.coordinate(center=21.74, radius=1.29) diff --git a/faker/providers/internet/mk_MK/__init__.py b/faker/providers/internet/mk_MK/__init__.py new file mode 100644 index 0000000000..b96c3576f7 --- /dev/null +++ b/faker/providers/internet/mk_MK/__init__.py @@ -0,0 +1,101 @@ +from .. import Provider as InternetProvider + + +class Provider(InternetProvider): + """Internet provider for mk_MK locale (Macedonian).""" + + user_name_formats = ( + "{{last_name_female}}.{{first_name_female}}", + "{{last_name_male}}.{{first_name_male}}", + "{{first_name_female}}.{{last_name_female}}", + "{{first_name_male}}.{{last_name_male}}", + "{{first_name}}##", + "?{{last_name}}", + "{{first_name}}{{year}}", + ) + + email_formats = ( + "{{user_name}}@{{free_email_domain}}", + "{{user_name}}@{{domain_name}}", + ) + + free_email_domains = ( + "gmail.com", + "yahoo.com", + "hotmail.com", + "on.net.mk", + "t.mk", + "telekom.mk", + "neotel.mk", + "alfa.mk", + "mail.mk", + "mtel.mk", + ) + + tlds = ("mk", "com", "net", "org", "edu", "gov.mk", "com.mk") + + # Macedonian Cyrillic → ASCII transliteration for usernames/domains + replacements = ( + ("а", "a"), + ("б", "b"), + ("в", "v"), + ("г", "g"), + ("д", "d"), + ("ѓ", "gj"), + ("е", "e"), + ("ж", "zh"), + ("з", "z"), + ("ѕ", "dz"), + ("и", "i"), + ("ј", "j"), + ("к", "k"), + ("л", "l"), + ("љ", "lj"), + ("м", "m"), + ("н", "n"), + ("њ", "nj"), + ("о", "o"), + ("п", "p"), + ("р", "r"), + ("с", "s"), + ("т", "t"), + ("ќ", "kj"), + ("у", "u"), + ("ф", "f"), + ("х", "h"), + ("ц", "ts"), + ("ч", "ch"), + ("џ", "dzh"), + ("ш", "sh"), + ("А", "a"), + ("Б", "b"), + ("В", "v"), + ("Г", "g"), + ("Д", "d"), + ("Ѓ", "gj"), + ("Е", "e"), + ("Ж", "zh"), + ("З", "z"), + ("Ѕ", "dz"), + ("И", "i"), + ("Ј", "j"), + ("К", "k"), + ("Л", "l"), + ("Љ", "lj"), + ("М", "m"), + ("Н", "n"), + ("Њ", "nj"), + ("О", "o"), + ("П", "p"), + ("Р", "r"), + ("С", "s"), + ("Т", "t"), + ("Ќ", "kj"), + ("У", "u"), + ("Ф", "f"), + ("Х", "h"), + ("Ц", "ts"), + ("Ч", "ch"), + ("Џ", "dzh"), + ("Ш", "sh"), + ) diff --git a/faker/providers/job/mk_MK/__init__.py b/faker/providers/job/mk_MK/__init__.py new file mode 100644 index 0000000000..f08f713574 --- /dev/null +++ b/faker/providers/job/mk_MK/__init__.py @@ -0,0 +1,73 @@ +from .. import Provider as BaseProvider + + +class Provider(BaseProvider): + """Job provider for mk_MK locale (Macedonian).""" + + jobs = ( + "Агроном", + "Адвокат", + "Администратор", + "Аналитичар", + "Архитект", + "Биолог", + "Биохемичар", + "Бравар", + "Ветеринар", + "Водоинсталатер", + "Возач", + "Геодет", + "Геолог", + "Градежен инженер", + "Графички дизајнер", + "Директор", + "Доктор по медицина", + "Економист", + "Електричар", + "Електроинженер", + "Електротехничар", + "Журналист", + "Ѕидар", + "Забар", + "Инспектор", + "Информатичар", + "Истражувач", + "Книговодител", + "Козметичар", + "Конструктор", + "Кувар", + "Лекар", + "Логопед", + "Мајстор", + "Машински инженер", + "Менаџер", + "Механичар", + "Молер", + "Наставник", + "Нотар", + "Нутриционист", + "Пекар", + "Пилот", + "Планер", + "Полицаец", + "Правник", + "Програмер", + "Психолог", + "Референт", + "Сoобраќаен инженер", + "Секретар", + "Сметководител", + "Социјален работник", + "Столар", + "Стоматолог", + "Судија", + "Технолог", + "Технолошки инженер", + "Трговец", + "Учител", + "Фармацевт", + "Физиотерапевт", + "Финансиски аналитичар", + "Хемичар", + "Шумар", + ) diff --git a/faker/providers/lorem/mk_MK/__init__.py b/faker/providers/lorem/mk_MK/__init__.py new file mode 100644 index 0000000000..a486d9a66f --- /dev/null +++ b/faker/providers/lorem/mk_MK/__init__.py @@ -0,0 +1,218 @@ +from typing import Dict + +from .. import Provider as LoremProvider + + +class Provider(LoremProvider): + """Lorem provider for mk_MK locale (Macedonian).""" + + word_list = ( + "луѓе", + "живот", + "работа", + "време", + "место", + "свет", + "земја", + "град", + "куќа", + "пат", + "ден", + "ноќ", + "вода", + "сонце", + "небо", + "страна", + "рака", + "очи", + "глава", + "срце", + "деца", + "мајка", + "татко", + "брат", + "сестра", + "пријател", + "љубов", + "среќа", + "мир", + "народ", + "слобода", + "правда", + "вистина", + "убавина", + "природа", + "шума", + "река", + "море", + "планина", + "село", + "улица", + "прозорец", + "врата", + "книга", + "музика", + "песна", + "уметност", + "историја", + "култура", + "јазик", + "зборови", + "мисла", + "чувство", + "сон", + "надеж", + "иднина", + "минато", + "сегашност", + "знаење", + "образование", + "наука", + "технологија", + "компјутер", + "интернет", + "телефон", + "информација", + "вест", + "проблем", + "решение", + "прашање", + "одговор", + "можност", + "промена", + "развиток", + "успех", + "цел", + "план", + "идеја", + "создавање", + "градење", + "заедница", + "семејство", + "пријателство", + "соработка", + "разбирање", + "доверба", + "поддршка", + "помош", + "грижа", + "здравје", + "храна", + "леб", + "вино", + "сол", + "светлина", + "темнина", + "топлина", + "студ", + "дожд", + "ветер", + "снег", + "оган", + "земјиште", + "камен", + "песок", + "злато", + "сребро", + "железо", + "дрво", + "лист", + "цвет", + "трева", + "жито", + "овошје", + "зеленчук", + "риба", + "птица", + "коњ", + "куче", + "мачка", + "волк", + "мечка", + "орел", + "небесен", + "длабок", + "висок", + "широк", + "тесен", + "голем", + "мал", + "стар", + "млад", + "убав", + "добар", + "лош", + "силен", + "слаб", + "брз", + "бавен", + "тивок", + "гласен", + "светол", + "темен", + "топол", + "ладен", + "тежок", + "лесен", + "трчи", + "оди", + "лета", + "пее", + "зборува", + "пишува", + "чита", + "гледа", + "слуша", + "мисли", + "сака", + "знае", + "може", + "дава", + "зема", + "прави", + "живее", + "расте", + "учи", + "работи", + "игра", + "спие", + "јаде", + "пие", + "смее", + "плаче", + "денес", + "утре", + "вчера", + "сега", + "тука", + "таму", + "многу", + "малку", + "секогаш", + "никогаш", + "брзо", + "полека", + "добро", + "лошо", + "заедно", + "сам", + "прво", + "потоа", + "пред", + "после", + "горе", + "доле", + "лево", + "десно", + "внатре", + "надвор", + "зошто", + "затоа", + "ако", + "кога", + "каде", + "кој", + "што", + ) + + parts_of_speech: Dict[str, tuple] = {} diff --git a/faker/providers/passport/mk_MK/__init__.py b/faker/providers/passport/mk_MK/__init__.py new file mode 100644 index 0000000000..ca33fedd5a --- /dev/null +++ b/faker/providers/passport/mk_MK/__init__.py @@ -0,0 +1,23 @@ +from faker.providers.passport import ElementsType +from faker.providers.passport import Provider as PassportProvider + + +class Provider(PassportProvider): + """Passport provider for mk_MK locale (Macedonian). + + Sources: + - https://en.wikipedia.org/wiki/Macedonian_passport + - https://en.wikipedia.org/wiki/Machine-readable_passport + + Passport types: + - P — Ordinary (burgundy cover, biometric) + - PD — Diplomatic + - PS — Official (службен) + + Number format: 1 uppercase letter + 7 digits (9-char MRZ field, padded with '<') + ICAO/MRZ country code: MKD + Validity: 2 years (under 4), 5 years (4–27), 10 years (27+) + """ + + # 1 letter + 7 digits — fits standard ICAO 9-char MRZ passport number field + passport_number_formats: ElementsType = ("?#######",) diff --git a/faker/providers/person/mk_MK/__init__.py b/faker/providers/person/mk_MK/__init__.py new file mode 100644 index 0000000000..9f766d0407 --- /dev/null +++ b/faker/providers/person/mk_MK/__init__.py @@ -0,0 +1,276 @@ +from .. import Provider as PersonProvider + + +class Provider(PersonProvider): + """Person provider for mk_MK locale (Macedonian).""" + + first_names_male = ( + "Александар", + "Алексеј", + "Андреј", + "Антон", + "Арсен", + "Атанас", + "Благој", + "Бојан", + "Борис", + "Борче", + "Бранко", + "Васил", + "Видое", + "Влатко", + "Гоце", + "Горан", + "Дамјан", + "Даниел", + "Дарко", + "Дејан", + "Димитар", + "Доне", + "Драган", + "Душан", + "Ѓорги", + "Ѓорче", + "Емил", + "Жарко", + "Зоран", + "Иван", + "Игор", + "Илија", + "Јане", + "Јован", + "Јовче", + "Кирил", + "Коста", + "Крсте", + "Кузман", + "Лазар", + "Лука", + "Марјан", + "Марко", + "Методи", + "Михаил", + "Митко", + "Момчило", + "Наум", + "Никола", + "Огнен", + "Павле", + "Петар", + "Петре", + "Ристо", + "Сашо", + "Симон", + "Слободан", + "Стефан", + "Стојан", + "Тихомир", + "Тодор", + "Томе", + "Трајан", + "Трајче", + "Филип", + "Христо", + "Цветан", + "Чедо", + ) + + first_names_female = ( + "Александра", + "Ана", + "Ангела", + "Анета", + "Анита", + "Билјана", + "Благица", + "Валентина", + "Василка", + "Васка", + "Весна", + "Виолета", + "Гордана", + "Даница", + "Данче", + "Дарија", + "Димка", + "Драгана", + "Елена", + "Елизабета", + "Емилија", + "Иванка", + "Јасмина", + "Јована", + "Катерина", + "Кристина", + "Лилјана", + "Лина", + "Магдалена", + "Маја", + "Марија", + "Марина", + "Мартина", + "Милена", + "Мирјана", + "Надица", + "Наташа", + "Невена", + "Нина", + "Оливера", + "Роза", + "Сања", + "Сара", + "Симона", + "Снежана", + "Соња", + "Софија", + "Стефанија", + "Сузана", + "Тања", + "Теодора", + "Тијана", + "Цвета", + "Цветанка", + ) + + last_names_male = ( + "Алексовски", + "Андоновски", + "Апостолов", + "Арсовски", + "Атанасов", + "Бојаџиев", + "Василев", + "Велјанов", + "Велков", + "Гавриловски", + "Георгиев", + "Глигоров", + "Ѓоргиев", + "Ѓорѓиевски", + "Гроздановски", + "Дамјановски", + "Дешановски", + "Димитриев", + "Димовски", + "Донев", + "Дурловски", + "Заев", + "Зафировски", + "Иванов", + "Илиев", + "Јанев", + "Јовановски", + "Јовчев", + "Климовски", + "Коцев", + "Крстев", + "Крстески", + "Лазаревски", + "Лазов", + "Марковски", + "Мартиновски", + "Матевски", + "Митревски", + "Михајловски", + "Младеновски", + "Мојсов", + "Мусијановски", + "Наумовски", + "Николов", + "Николовски", + "Пановски", + "Петковски", + "Петровски", + "Поповски", + "Ристовски", + "Симоновски", + "Спасов", + "Спасовски", + "Стефановски", + "Стојановски", + "Тодоровски", + "Трајковски", + "Христов", + "Цветковски", + "Чулев", + "Шакири", + ) + + last_names_female = ( + "Алексовска", + "Андоновска", + "Апостолова", + "Арсовска", + "Атанасова", + "Бојаџиева", + "Василева", + "Велјанова", + "Велкова", + "Гавриловска", + "Георгиева", + "Глигорова", + "Ѓоргиева", + "Ѓорѓиевска", + "Гроздановска", + "Дамјановска", + "Дешановска", + "Димитриева", + "Димовска", + "Донева", + "Дурловска", + "Заева", + "Зафировска", + "Иванова", + "Илиева", + "Јанева", + "Јовановска", + "Јовчева", + "Климовска", + "Коцева", + "Крстева", + "Крстеска", + "Лазаревска", + "Лазова", + "Марковска", + "Мартиновска", + "Матевска", + "Митревска", + "Михајловска", + "Младеновска", + "Мојсова", + "Николова", + "Николовска", + "Пановска", + "Петковска", + "Петровска", + "Поповска", + "Ристовска", + "Симоновска", + "Спасова", + "Спасовска", + "Стефановска", + "Стојановска", + "Тодоровска", + "Трајковска", + "Христова", + "Цветковска", + "Чулева", + "Шакири", + ) + + prefixes_male = ("Г-н", "Др.", "Проф.") + prefixes_female = ("Г-ѓа", "Г-ца", "Др.", "Проф.") + + formats_male = ( + "{{first_name_male}} {{last_name_male}}", + "{{prefix_male}} {{first_name_male}} {{last_name_male}}", + ) + + formats_female = ( + "{{first_name_female}} {{last_name_female}}", + "{{prefix_female}} {{first_name_female}} {{last_name_female}}", + ) + + formats = formats_male + formats_female + first_names = first_names_male + first_names_female + last_names = last_names_male + last_names_female diff --git a/faker/providers/phone_number/mk_MK/__init__.py b/faker/providers/phone_number/mk_MK/__init__.py new file mode 100644 index 0000000000..672d0d2b14 --- /dev/null +++ b/faker/providers/phone_number/mk_MK/__init__.py @@ -0,0 +1,31 @@ +from .. import Provider as PhoneNumberProvider + + +class Provider(PhoneNumberProvider): + """Phone number provider for mk_MK locale (Macedonian). + + Country code: +389 + Skopje area code: 02 + Other area codes: 03x + Mobile prefixes: 07x + """ + + formats = ( + "+389(0)#########", + "+389(0)## ######", + "+389(0)## ### ###", + "+3892#########", + "02#########", + "02## ######", + "02## ### ###", + "070 ### ###", + "071 ### ###", + "072 ### ###", + "075 ### ###", + "076 ### ###", + "077 ### ###", + "078 ### ###", + "+38970 ### ###", + "+38971 ### ###", + "+38972 ### ###", + ) diff --git a/faker/providers/ssn/mk_MK/__init__.py b/faker/providers/ssn/mk_MK/__init__.py new file mode 100644 index 0000000000..1ab8ccfd6a --- /dev/null +++ b/faker/providers/ssn/mk_MK/__init__.py @@ -0,0 +1,62 @@ +from .. import Provider as SsnProvider + + +class Provider(SsnProvider): + """SSN provider for mk_MK locale (Macedonian). + + The Macedonian EMBG (Единствен матичен број на граѓанинот) is a 13-digit + unique citizen identification number with the format: + + DDMMYYYRRGBBK + + where: + DD - day of birth (01-31) + MM - month of birth (01-12) + YYY - last 3 digits of year of birth + RR - region code (North Macedonia uses 41) + G - gender and century digit (0-4 female, 5-9 male; odd=1900s, even=2000s) + BB - sequence number within region/gender/day (00-99) + K - checksum digit (MOD 11) + """ + + # North Macedonia region code + REGION_CODE = "41" + + @staticmethod + def _checksum(digits: list) -> int: + weights = [7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2] + total = sum(w * d for w, d in zip(weights, digits)) + remainder = 11 - (total % 11) + if remainder in (10, 11): + return 0 + return remainder + + def ssn(self) -> str: + """Generate a valid Macedonian EMBG number.""" + rng = self.generator.random + + # Random birth date between 1950 and 2005 + birth_year = rng.randint(1950, 2005) + birth_month = rng.randint(1, 12) + # Simplified: use day range 1-28 to avoid invalid dates + birth_day = rng.randint(1, 28) + + dd = f"{birth_day:02d}" + mm = f"{birth_month:02d}" + yyy = f"{birth_year % 1000:03d}" + + rr = self.REGION_CODE + + # Gender: 0-4 female (born 1900s: odd, 2000s: even), 5-9 male + is_male = rng.choice([True, False]) + if is_male: + g = rng.randint(5, 9) + else: + g = rng.randint(0, 4) + + bb = f"{rng.randint(0, 99):02d}" + + digits = [int(c) for c in dd + mm + yyy + rr + str(g) + bb] + k = self._checksum(digits) + + return dd + mm + yyy + rr + str(g) + bb + str(k) diff --git a/tests/providers/test_address.py b/tests/providers/test_address.py index cb692b89fc..a504c7c225 100644 --- a/tests/providers/test_address.py +++ b/tests/providers/test_address.py @@ -41,6 +41,7 @@ from faker.providers.address.ja_JP import Provider as JaJpAddressProvider from faker.providers.address.ka_GE import Provider as KaGeAddressProvider from faker.providers.address.ko_KR import Provider as KoKrAddressProvider +from faker.providers.address.mk_MK import Provider as MkMKAddressProvider from faker.providers.address.ne_NP import Provider as NeNpAddressProvider from faker.providers.address.no_NO import Provider as NoNoAddressProvider from faker.providers.address.pl_PL import Provider as PlPlAddressProvider @@ -1384,6 +1385,34 @@ def test_country(self, faker, num_samples): assert country in NeNpAddressProvider.countries +class TestMkMk: + """Test mk_MK address provider methods""" + + def test_city_name(self, faker, num_samples): + for _ in range(num_samples): + city = faker.city_name() + assert isinstance(city, str) + assert city in MkMKAddressProvider.cities + + def test_street_name(self, faker, num_samples): + for _ in range(num_samples): + street = faker.street_name() + assert isinstance(street, str) + assert street in MkMKAddressProvider.streets + + def test_state(self, faker, num_samples): + for _ in range(num_samples): + state = faker.state() + assert isinstance(state, str) + assert state in MkMKAddressProvider.states + + def test_address(self, faker, num_samples): + for _ in range(num_samples): + address = faker.address() + assert isinstance(address, str) + assert len(address) > 0 + + class TestNoNo: """Test no_NO address provider methods""" diff --git a/tests/providers/test_automotive.py b/tests/providers/test_automotive.py index 618593dc7f..8c3c96dfd2 100644 --- a/tests/providers/test_automotive.py +++ b/tests/providers/test_automotive.py @@ -7,6 +7,7 @@ from faker.providers.automotive.de_AT import Provider as DeAtAutomotiveProvider from faker.providers.automotive.de_DE import Provider as DeDeAutomotiveProvider from faker.providers.automotive.es_ES import Provider as EsEsAutomotiveProvider +from faker.providers.automotive.mk_MK import Provider as MkMKAutomotiveProvider from faker.providers.automotive.ro_RO import Provider as RoRoAutomotiveProvider from faker.providers.automotive.ru_RU import Provider as RuRuAutomotiveProvider from faker.providers.automotive.sk_SK import Provider as SkSkAutomotiveProvider @@ -414,3 +415,16 @@ class TestZhTw(_SimpleAutomotiveTestMixin): r"([A-Z]{3}-\d{4})|" # new format since 2014 r"([A-Z]{3}-\d{3})", # commercial cars since 2012 ) + + +class TestMkMk(_SimpleAutomotiveTestMixin): + """Test mk_MK automotive provider methods""" + + # Format: XX NNNN YY (2-letter region, 4 digits, 2 letters) + license_plate_pattern: Pattern = re.compile(r"[A-Z]{2} \d{4} [A-BCDEFGHIJKLMNOPRSTUVZ]{2}") + + def test_license_plate_prefix(self, faker, num_samples): + for _ in range(num_samples): + plate = faker.license_plate() + prefix = plate.split()[0] + assert prefix in MkMKAutomotiveProvider.license_plate_prefixes diff --git a/tests/providers/test_bank.py b/tests/providers/test_bank.py index 69bcf3bf29..ec3552e276 100644 --- a/tests/providers/test_bank.py +++ b/tests/providers/test_bank.py @@ -16,6 +16,7 @@ from faker.providers.bank.es_MX import is_valid_clabe from faker.providers.bank.fi_FI import Provider as FiFiBankProvider from faker.providers.bank.fr_FR import Provider as FrFrBankProvider +from faker.providers.bank.mk_MK import Provider as MkMKBankProvider from faker.providers.bank.nl_BE import Provider as NlBeBankProvider from faker.providers.bank.no_NO import Provider as NoNoBankProvider from faker.providers.bank.pl_PL import Provider as PlPlBankProvider @@ -526,3 +527,20 @@ def test_bank_not_implemented_error(self, faker): with pytest.raises(AttributeError): provider.bank() + + +class TestMkMk: + """Test mk_MK bank provider methods""" + + def test_bank(self, faker, num_samples): + for _ in range(num_samples): + bank = faker.bank() + assert isinstance(bank, str) + assert bank in MkMKBankProvider.banks + + def test_iban(self, faker, num_samples): + for _ in range(num_samples): + iban = faker.iban() + assert isinstance(iban, str) + assert iban.startswith("MK") + assert len(iban) == 21 # MK(2) + check(2) + bban(17) diff --git a/tests/providers/test_color.py b/tests/providers/test_color.py index 53b0442dca..4c7a8f2a3d 100644 --- a/tests/providers/test_color.py +++ b/tests/providers/test_color.py @@ -20,6 +20,7 @@ from faker.providers.color.hy_AM import Provider as HyAmColorProvider from faker.providers.color.id_ID import Provider as IdIdColorProvider from faker.providers.color.ka_GE import Provider as KaGEColorProvider +from faker.providers.color.mk_MK import Provider as MkMKColorProvider from faker.providers.color.sk_SK import Provider as SkSkColorProvider from faker.providers.color.uz_UZ import Provider as UzUzColorProvider from faker.providers.color.vi_VN import Provider as ViVNColorProvider @@ -528,3 +529,19 @@ def test_safe_color_name(self, faker, num_samples): safe_color_name = faker.safe_color_name() assert isinstance(safe_color_name, str) assert safe_color_name in UzUzColorProvider.safe_colors + + +class TestMkMk: + """Test mk_MK color provider methods""" + + def test_color_name(self, faker, num_samples): + for _ in range(num_samples): + color_name = faker.color_name() + assert isinstance(color_name, str) + assert color_name in MkMKColorProvider.all_colors.keys() + + def test_safe_color_name(self, faker, num_samples): + for _ in range(num_samples): + safe_color_name = faker.safe_color_name() + assert isinstance(safe_color_name, str) + assert safe_color_name in MkMKColorProvider.safe_colors diff --git a/tests/providers/test_company.py b/tests/providers/test_company.py index 09d4981dfa..6a94dd0658 100644 --- a/tests/providers/test_company.py +++ b/tests/providers/test_company.py @@ -18,6 +18,7 @@ from faker.providers.company.it_IT import Provider as ItItCompanyProvider from faker.providers.company.ja_JP import Provider as JaJpCompanyProvider from faker.providers.company.ko_KR import Provider as KoKrCompanyProvider +from faker.providers.company.mk_MK import Provider as MkMKCompanyProvider from faker.providers.company.nl_BE import Provider as NlBeCompanyProvider from faker.providers.company.nl_NL import Provider as NlNlCompanyProvider from faker.providers.company.pl_PL import Provider as PlPlCompanyProvider @@ -620,3 +621,18 @@ def test_company(self, faker, num_samples): for _ in range(num_samples): company = faker.company() assert isinstance(company, str) + + +class TestMkMk: + """Test mk_MK company provider methods""" + + def test_company(self, faker, num_samples): + for _ in range(num_samples): + company = faker.company() + assert isinstance(company, str) + + def test_company_suffix(self, faker, num_samples): + for _ in range(num_samples): + suffix = faker.company_suffix() + assert isinstance(suffix, str) + assert suffix in MkMKCompanyProvider.company_suffixes diff --git a/tests/providers/test_currency.py b/tests/providers/test_currency.py index b9ca42c40f..bf54cf4111 100644 --- a/tests/providers/test_currency.py +++ b/tests/providers/test_currency.py @@ -4,6 +4,8 @@ import pytest +from faker.providers.currency.mk_MK import Provider as MkMKCurrencyProvider + class TestCurrencyProvider: """Test currency provider methods""" @@ -633,3 +635,30 @@ def test_pricetag(self, faker, num_samples): for _ in range(num_samples): pricetag = faker.pricetag() assert isinstance(pricetag, str) + + +class TestMkMk: + """Test mk_MK currency provider methods""" + + def test_currency(self, faker, num_samples): + codes = [c for c, _ in MkMKCurrencyProvider.currencies] + names = [n for _, n in MkMKCurrencyProvider.currencies] + for _ in range(num_samples): + cur = faker.currency() + assert isinstance(cur, tuple) + assert cur[0] in codes + assert cur[1] in names + + def test_currency_name(self, faker, num_samples): + names = [n for _, n in MkMKCurrencyProvider.currencies] + for _ in range(num_samples): + name = faker.currency_name() + assert isinstance(name, str) + assert name in names + + def test_currency_code(self, faker, num_samples): + codes = [c for c, _ in MkMKCurrencyProvider.currencies] + for _ in range(num_samples): + code = faker.currency_code() + assert isinstance(code, str) + assert code in codes diff --git a/tests/providers/test_date_time.py b/tests/providers/test_date_time.py index f7e6ce4301..8f36b864a5 100644 --- a/tests/providers/test_date_time.py +++ b/tests/providers/test_date_time.py @@ -33,6 +33,7 @@ from faker.providers.date_time.it_IT import Provider as ItItProvider from faker.providers.date_time.ja_JP import Provider as JaJpProvider from faker.providers.date_time.ka_GE import Provider as KaGeProvider +from faker.providers.date_time.mk_MK import Provider as MkMKDateTimeProvider from faker.providers.date_time.nl_NL import Provider as NlProvider from faker.providers.date_time.no_NO import Provider as NoNoProvider from faker.providers.date_time.pl_PL import Provider as PlProvider @@ -1441,3 +1442,23 @@ def test_month(self): month = self.fake.month_name() assert isinstance(month, str) assert month in UzUzProvider.MONTH_NAMES.values() + + +class TestMkMk(unittest.TestCase): + """Tests date_time in the mk_MK locale""" + + def setUp(self): + self.fake = Faker("mk_MK") + Faker.seed(0) + + def test_day(self): + for _ in range(50): + day = self.fake.day_of_week() + assert isinstance(day, str) + assert day in MkMKDateTimeProvider.DAY_NAMES.values() + + def test_month(self): + for _ in range(50): + month = self.fake.month_name() + assert isinstance(month, str) + assert month in MkMKDateTimeProvider.MONTH_NAMES.values() diff --git a/tests/providers/test_geo.py b/tests/providers/test_geo.py index 8e303494e1..1e3134ab86 100644 --- a/tests/providers/test_geo.py +++ b/tests/providers/test_geo.py @@ -168,3 +168,21 @@ class TestEnIe(TestEnUS): def setUp(self): self.fake = Faker("en_IE") Faker.seed(0) + + +class TestMkMk(unittest.TestCase): + """Tests geo provider for mk_MK locale""" + + def setUp(self): + self.fake = Faker("mk_MK") + Faker.seed(0) + + def test_local_latitude(self): + for _ in range(100): + lat = self.fake.local_latitude() + assert 40.85 <= float(lat) <= 42.37, f"Latitude {lat} out of MK bounds" + + def test_local_longitude(self): + for _ in range(100): + lon = self.fake.local_longitude() + assert 20.45 <= float(lon) <= 23.03, f"Longitude {lon} out of MK bounds" diff --git a/tests/providers/test_internet.py b/tests/providers/test_internet.py index d8f1fb788c..3011b2f65b 100644 --- a/tests/providers/test_internet.py +++ b/tests/providers/test_internet.py @@ -15,6 +15,7 @@ from faker.providers.internet.en_GB import Provider as EnGbInternetProvider from faker.providers.internet.es_ES import Provider as EsEsInternetProvider from faker.providers.internet.hu_HU import Provider as HuHuInternetProvider +from faker.providers.internet.mk_MK import Provider as MkMKInternetProvider from faker.providers.internet.pl_PL import Provider as PlPlInternetProvider from faker.providers.internet.pt_BR import Provider as PtBrInternetProvider from faker.providers.internet.ro_RO import Provider as RoRoInternetProvider @@ -996,3 +997,23 @@ def test_slug(self, faker): num_of_samples = 100 for _ in range(num_of_samples): assert faker.slug() != "" + + +class TestMkMk: + """Test mk_MK internet provider methods""" + + def test_free_email_domain(self, faker, num_samples): + for _ in range(num_samples): + domain = faker.free_email_domain() + assert domain in MkMKInternetProvider.free_email_domains + + def test_tld(self, faker, num_samples): + for _ in range(num_samples): + tld = faker.tld() + assert tld in MkMKInternetProvider.tlds + + def test_email(self, faker, num_samples): + for _ in range(num_samples): + email = faker.email() + assert isinstance(email, str) + assert "@" in email diff --git a/tests/providers/test_job.py b/tests/providers/test_job.py index b405e324a4..6db934e99f 100644 --- a/tests/providers/test_job.py +++ b/tests/providers/test_job.py @@ -11,6 +11,7 @@ from faker.providers.job.ja_JP import Provider as JaJpJobProvider from faker.providers.job.ka_GE import Provider as KaGeJobProvider from faker.providers.job.ko_KR import Provider as KoKrJobProvider +from faker.providers.job.mk_MK import Provider as MkMKJobProvider from faker.providers.job.pt_BR import Provider as PtBrJobProvider from faker.providers.job.pt_PT import Provider as PtPtJobProvider from faker.providers.job.ro_RO import Provider as RoRoJobProvider @@ -185,3 +186,13 @@ def test_job(self, faker, num_samples): job = faker.job() assert isinstance(job, str) assert job in ViVNJobProvider.jobs + + +class TestMkMk: + """Test mk_MK job provider methods""" + + def test_job(self, faker, num_samples): + for _ in range(num_samples): + job = faker.job() + assert isinstance(job, str) + assert job in MkMKJobProvider.jobs diff --git a/tests/providers/test_lorem.py b/tests/providers/test_lorem.py index 0182f229be..8155bff5ee 100644 --- a/tests/providers/test_lorem.py +++ b/tests/providers/test_lorem.py @@ -13,6 +13,7 @@ from faker.providers.lorem.es_MX import Provider as EsMxLoremProvider from faker.providers.lorem.fa_IR import Provider as FaIrLoremProvider from faker.providers.lorem.it_IT import Provider as ItItLoremProvider +from faker.providers.lorem.mk_MK import Provider as MkMKLoremProvider from faker.providers.lorem.nl_BE import Provider as NlBeLoremProvider from faker.providers.lorem.uk_UA import Provider as UkUaLoremProvider from faker.providers.lorem.vi_VN import Provider as ViVNLoremProvider @@ -1084,3 +1085,22 @@ def test_words(self, faker, num_samples): for _ in range(num_samples): words = faker.words(num_words) assert all(isinstance(word, str) and word in EsEsLoremProvider.word_list for word in words) + + +class TestMkMk: + """Test mk_MK lorem provider methods""" + + def test_word(self, faker, num_samples): + word_list = [w.lower() for w in MkMKLoremProvider.word_list] + for _ in range(num_samples): + word = faker.word() + assert isinstance(word, str) + assert word.lower() in word_list + + def test_sentence(self, faker, num_samples): + word_list = [w.lower() for w in MkMKLoremProvider.word_list] + for _ in range(num_samples): + sentence = faker.sentence() + assert isinstance(sentence, str) + words = sentence.replace(".", "").split() + assert all(w.lower() in word_list for w in words) diff --git a/tests/providers/test_passport.py b/tests/providers/test_passport.py index 5316b29e6d..59cb9a2214 100644 --- a/tests/providers/test_passport.py +++ b/tests/providers/test_passport.py @@ -39,3 +39,14 @@ def test_passport_number(self, faker, num_samples): for _ in range(num_samples): passport_number = faker.passport_number() assert pattern.fullmatch(passport_number) + + +class TestMkMk: + """Test mk_MK passport provider methods""" + + def test_passport_number(self, faker, num_samples): + # Format: 1 uppercase letter + 7 digits + pattern = re.compile(r"^[A-Z]\d{7}$") + for _ in range(num_samples): + passport_number = faker.passport_number() + assert pattern.fullmatch(passport_number), f"Unexpected format: {passport_number!r}" diff --git a/tests/providers/test_person.py b/tests/providers/test_person.py index b3bd4c31de..97be04ee9c 100644 --- a/tests/providers/test_person.py +++ b/tests/providers/test_person.py @@ -35,6 +35,7 @@ from faker.providers.person.ig_NG import Provider as IgNgProvider from faker.providers.person.is_IS import Provider as IsISProvider from faker.providers.person.lv_LV import Provider as LvProvider +from faker.providers.person.mk_MK import Provider as MkMKProvider from faker.providers.person.ne_NP import Provider as NeProvider from faker.providers.person.nl_BE import Provider as NlBEProvider from faker.providers.person.or_IN import Provider as OrINProvider @@ -1444,6 +1445,51 @@ def test_last_name(self): assert name in LvProvider.last_names_male +class TestMkMk(unittest.TestCase): + """Tests for mk_MK locale person provider""" + + def setUp(self): + self.fake = Faker("mk_MK") + Faker.seed(0) + + def test_first_name(self): + name = self.fake.first_name() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.first_names + + name = self.fake.first_name_female() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.first_names_female + + name = self.fake.first_name_male() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.first_names_male + + def test_last_name(self): + name = self.fake.last_name() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.last_names + + name = self.fake.last_name_female() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.last_names_female + + name = self.fake.last_name_male() + assert name + self.assertIsInstance(name, str) + assert name in MkMKProvider.last_names_male + + def test_name(self): + name = self.fake.name() + assert name + self.assertIsInstance(name, str) + + class TestNeNP(unittest.TestCase): def setUp(self): self.fake = Faker("ne_NP") diff --git a/tests/providers/test_phone_number.py b/tests/providers/test_phone_number.py index bfd3603465..3d0a18269e 100644 --- a/tests/providers/test_phone_number.py +++ b/tests/providers/test_phone_number.py @@ -555,3 +555,15 @@ def test_phone_number(self, faker, num_samples): phone_number = faker.phone_number() assert isinstance(phone_number, str) assert pattern.fullmatch(phone_number) + + +class TestMkMk: + """Test mk_MK phone number provider methods""" + + def test_phone_number(self, faker, num_samples): + # Macedonian numbers start with +389, 02, 03x, or 07x + pattern: Pattern = re.compile(r"(\+389[\d\s\(\)]+|0[237]\d[\d\s]+)") + for _ in range(num_samples): + phone = faker.phone_number() + assert isinstance(phone, str) + assert pattern.match(phone), f"Unexpected phone format: {phone!r}" diff --git a/tests/providers/test_ssn.py b/tests/providers/test_ssn.py index c9d4ad7544..ec7e0df4f7 100644 --- a/tests/providers/test_ssn.py +++ b/tests/providers/test_ssn.py @@ -27,6 +27,7 @@ from faker.providers.ssn.hr_HR import checksum as hr_checksum from faker.providers.ssn.it_IT import checksum as it_checksum from faker.providers.ssn.lv_LV import Provider as lv_Provider +from faker.providers.ssn.mk_MK import Provider as MkMKSsnProvider from faker.providers.ssn.no_NO import Provider as no_Provider from faker.providers.ssn.no_NO import checksum as no_checksum from faker.providers.ssn.pl_PL import calculate_month as pl_calculate_mouth @@ -1451,3 +1452,23 @@ def test_incorrect_birthday(self): def test_incorrect_gender(self): with pytest.raises(ValueError): self.fake.ssn(gender="f") + + +class TestMkMk(unittest.TestCase): + """Tests SSN (EMBG) in the mk_MK locale""" + + def setUp(self): + self.fake = Faker("mk_MK") + Faker.seed(0) + + def test_ssn_format(self): + for _ in range(100): + ssn = self.fake.ssn() + assert re.match(r"^\d{13}$", ssn), f"EMBG {ssn!r} is not 13 digits" + + def test_ssn_checksum(self): + for _ in range(100): + ssn = self.fake.ssn() + digits = [int(c) for c in ssn[:12]] + expected_check = MkMKSsnProvider._checksum(digits) + assert int(ssn[12]) == expected_check, f"Bad checksum in {ssn}"