From 7b4aefdc20852ffa76872addf0cc605a7d9842ad Mon Sep 17 00:00:00 2001 From: Gornyh Date: Mon, 16 Mar 2026 17:40:58 +0300 Subject: [PATCH 1/3] 3 files added. Code refactoring, test, and description. --- python/GornyhIS.md | 31 ++++++++++++++++++++ python/funding_ref.py | 66 +++++++++++++++++++++++++++++++++++++++++++ python/test_ref.py | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 python/GornyhIS.md create mode 100644 python/funding_ref.py create mode 100644 python/test_ref.py diff --git a/python/GornyhIS.md b/python/GornyhIS.md new file mode 100644 index 0000000..5a02ebe --- /dev/null +++ b/python/GornyhIS.md @@ -0,0 +1,31 @@ +🔍 Анализ проблемы в исходном коде + + +## Повторное чтение файла: + +Методы where и find_by каждый раз открывают и читают CSV. +Рефакторинг: добавлено кэширование через _load_data. + +## Дублирование кода: + +Одинаковые блоки фильтрации и маппинга в where и find_by. +Рефакторинг: вынесена общая логика фильтрации и маппинга. + +## обработка find_by: + +find_by возвращал первую найденную запись по одному полю, +но не учитывал комбинации условий. +Теперь find_by использует where, что гарантирует консистентность. + +## Отсутствие обработки кодировки: + +Добавлен encoding="utf-8" для надежности. + +## Стиль и архитектура: + +Использование @staticmethod вместо @classmethod. +RecordNotFound определён внизу, лучше его вынести наверх. + +## Нет проверки на пустые результаты в find_by: + +Теперь корректно выбрасывается исключение RecordNotFound. \ No newline at end of file diff --git a/python/funding_ref.py b/python/funding_ref.py new file mode 100644 index 0000000..7046fd6 --- /dev/null +++ b/python/funding_ref.py @@ -0,0 +1,66 @@ +import csv + +class RecordNotFound(Exception): + """Исключение, выбрасываемое, когда запись не найдена.""" + pass + +class FundingRaised: + # Кэшируем данные CSV, чтобы не читать файл каждый раз + _cached_data = None + + @classmethod + def _load_data(cls): + """Загружает данные из CSV один раз и кэширует их.""" + if cls._cached_data is None: + with open("../startup_funding.csv", "rt", encoding="utf-8") as csvfile: + reader = csv.reader(csvfile, delimiter=',', quotechar='"') + next(reader) # Пропускаем заголовок + cls._cached_data = [row for row in reader] + return cls._cached_data + + @staticmethod + def _map_row(row): + """Преобразует строку CSV в словарь с нужными ключами.""" + keys = [ + 'permalink', 'company_name', 'number_employees', 'category', + 'city', 'state', 'funded_date', 'raised_amount', + 'raised_currency', 'round' + ] + return dict(zip(keys, row)) + + @classmethod + def where(cls, options=None): + """ + Возвращает список всех записей, соответствующих условиям. + Поддерживает фильтрацию по: company_name, city, state, round. + """ + if options is None: + options = {} + + data = cls._load_data() + filtered_data = data + + # Фильтрация по каждому полю + filters = { + 'company_name': 1, + 'city': 4, + 'state': 5, + 'round': 9 + } + + for key, index in filters.items(): + if key in options: + filtered_data = [row for row in filtered_data if row[index] == options[key]] + + return [cls._map_row(row) for row in filtered_data] + + @classmethod + def find_by(cls, options): + """ + Возвращает первую запись, соответствующую условиям. + Выбрасывает RecordNotFound, если ничего не найдено. + """ + result = cls.where(options) + if not result: + raise RecordNotFound(f"Запись с параметрами {options} не найдена.") + return result[0] \ No newline at end of file diff --git a/python/test_ref.py b/python/test_ref.py new file mode 100644 index 0000000..ec20e6a --- /dev/null +++ b/python/test_ref.py @@ -0,0 +1,63 @@ +from funding_ref import FundingRaised + + +def test_where_returns_events(): + assert len(FundingRaised.where({'company_name': 'Facebook'})) == 7 + + +def test_where_returns_correct_keys(): + row = FundingRaised.where({'company_name': 'Facebook'})[0] + keys = ['permalink', 'company_name', 'number_employees', 'category', 'city', 'state', 'funded_date', + 'raised_amount', 'raised_currency', 'round'] + values = ['facebook', 'Facebook', '450', 'web', 'Palo Alto', 'CA', '1-Sep-04', '500000', 'USD', 'angel'] + for i in range(0, len(keys)): + assert row[keys[i]] == values[i] + + +def test_where_returns_events_by_city(): + assert len(FundingRaised.where({'city': 'Tempe'})) == 3 + + +def test_where_returns_events_by_state(): + assert len(FundingRaised.where({'state': 'CA'})) == 873 + + +def test_where_returns_events_by_company(): + assert len(FundingRaised.where({'company_name': 'Facebook', 'round': 'a'})) == 1 + + +def test_where_returns_events_by_type(): + assert len(FundingRaised.where({'round': 'a'})) == 582 + + +def test_where_returns_no_events(): + assert len(FundingRaised.where({'company_name': 'NotFacebook'})) == 0 + + +def test_find_by_event_by_company_name(): + row = FundingRaised.find_by({'company_name': 'Facebook'}) + keys = ['permalink', 'company_name', 'number_employees', 'category', 'city', 'state', 'funded_date', + 'raised_amount', 'raised_currency', 'round'] + values = ['facebook', 'Facebook', '450', 'web', 'Palo Alto', 'CA', '1-Sep-04', '500000', 'USD', 'angel'] + for i in range(0, len(keys)): + assert row[keys[i]] == values[i] + + +def test_find_by_event_by_state(): + row = FundingRaised.find_by({'state': 'CA'}) + keys = ['permalink', 'company_name', 'number_employees', 'category', 'city', 'state', 'funded_date', + 'raised_amount', 'raised_currency', 'round'] + values = ['digg', 'Digg', '60', 'web', 'San Francisco', 'CA', '1-Dec-06', '8500000', 'USD', 'b'] + for i in range(0, len(keys)): + assert row[keys[i]] == values[i] + + +test_where_returns_events() +test_where_returns_correct_keys() +test_where_returns_events_by_city() +test_where_returns_events_by_state() +test_where_returns_events_by_company() +test_where_returns_events_by_type() +test_where_returns_no_events() +test_find_by_event_by_company_name() +test_find_by_event_by_state() From 0cf77cb7ec1e7a9ab16fd86598d34b3d50980b9e Mon Sep 17 00:00:00 2001 From: Gornyh Date: Mon, 16 Mar 2026 17:44:27 +0300 Subject: [PATCH 2/3] 3 files added. Code refactoring (funding_ref.py), test (test_ref.py), and description (GornyhIS.md). --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f1e9fb4..f98f7fa 100755 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node/node_modules +/python/ From 22ca19872c3969e5015a84fc4779fe0a9a9be2d6 Mon Sep 17 00:00:00 2001 From: Gornyh Date: Mon, 16 Mar 2026 17:47:10 +0300 Subject: [PATCH 3/3] 3 files added. Code refactoring (funding_ref.py), test (test_ref.py), and description (GornyhIS.md). --- python/GornyhIS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/GornyhIS.md b/python/GornyhIS.md index 5a02ebe..d92bdae 100644 --- a/python/GornyhIS.md +++ b/python/GornyhIS.md @@ -1,5 +1,6 @@ -🔍 Анализ проблемы в исходном коде +## Горных ИС +🔍 Анализ проблемы в исходном коде ## Повторное чтение файла: