def adjust_ratios(amounts): """ Adjusts the ratios of given amounts so that their total becomes 100%. Args: amounts (list of float): A list of amounts to be adjusted. Returns: list of float: Adjusted ratios rounded to two decimal places. Raises: ValueError: If any of the amounts are negative. """ # Validate input amounts if any(amount < 0 for amount in amounts): raise ValueError("All amounts must be non-negative.") # Calculate the ratios total_amount = sum(amounts) ratios = [amount / total_amount for amount in amounts] # Round the ratios to two decimal places and calculate the rounded total rounded_ratios = [round(ratio * 100, 2) for ratio in ratios] rounded_total = sum(rounded_ratios) # Adjust the difference to ensure the total is exactly 100% difference = 100 - rounded_total max_ratio_index = rounded_ratios.index(max(rounded_ratios)) rounded_ratios[max_ratio_index] += difference return rounded_ratios# データベース格納先ディレクトリとファイル名 SQLITE_CONFIG = { 'db_dir': 'db', 'db_filename': 'demo.db' } import os def create_directory_structure(project_name): # プロジェクトのルートディレクトリを作成 os.makedirs(project_name) # srcディレクトリを作成 src_dir = os.path.join(project_name, 'src') os.makedirs(src_dir) # app.py, database.py, utils.pyを作成 open(os.path.join(src_dir, 'app.py'), 'a').close() open(os.path.join(src_dir, 'database.py'), 'a').close() open(os.path.join(src_dir, 'utils.py'), 'a').close() # testsディレクトリを作成 tests_dir = os.path.join(project_name, 'tests') os.makedirs(tests_dir) # test_database.py, test_utils.pyを作成 open(os.path.join(tests_dir, 'test_database.py'), 'a').close() open(os.path.join(tests_dir, 'test_utils.py'), 'a').close() # dbディレクトリを作成 db_dir = os.path.join(project_name, 'db') os.makedirs(db_dir) # test_database.dbを作成 open(os.path.join(db_dir, 'test_database.db'), 'a').close() # requirements.txtを作成 with open(os.path.join(project_name, 'requirements.txt'), 'w') as f: f.write('# プロジェクトの依存関係を記述\n') # README.mdを作成 with open(os.path.join(project_name, 'README.md'), 'w') as f: f.write('# ' + project_name + '\n') f.write('プロジェクトの概要や使い方をここに記述\n') # .gitignoreを作成 with open(os.path.join(project_name, '.gitignore'), 'w') as f: f.write('# Gitの管理下に置かれるべきでないファイルやディレクトリを指定\n') f.write('*.pyc\n') f.write('__pycache__/\n') f.write('db/*.db\n') if __name__ == "__main__": project_name = "backend_project" create_directory_structure(project_name) print(f"ディレクトリ構造 '{project_name}' が作成されました。") import sqlite3 import pandas as pd def generate_table_definitions_with_indexes(database_file, output_excel): # SQLiteデータベースに接続 conn = sqlite3.connect(database_file) cursor = conn.cursor() # テーブルの一覧を取得 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables = cursor.fetchall() # テーブル定義情報用のDataFrameを作成 table_definitions = pd.DataFrame(columns=['Table Name', 'Column Name', 'Data Type', 'Primary Key']) # インデックス情報用のDataFrameを作成 index_definitions = pd.DataFrame(columns=['Table Name', 'Index Name', 'Column Name']) for table in tables: table_name = table[0] # テーブルのカラム情報を取得 cursor.execute(f"PRAGMA table_info({table_name})") table_info = cursor.fetchall() for column_info in table_info: column_name = column_info[1] data_type = column_info[2] is_primary_key = "Yes" if column_info[5] == 1 else "No" table_definitions = pd.concat([table_definitions, pd.DataFrame({ 'Table Name': [table_name], 'Column Name': [column_name], 'Data Type': [data_type], 'Primary Key': [is_primary_key] })], ignore_index=True) # テーブルのインデックス情報を取得 cursor.execute(f"PRAGMA index_list({table_name})") index_list = cursor.fetchall() for index_info in index_list: index_name = index_info[1] # インデックスに含まれるカラムを取得 cursor.execute(f"PRAGMA index_info({index_name})") index_info_details = cursor.fetchall() for detail in index_info_details: column_name = detail[2] # インデックスに含まれるカラム名 index_definitions = pd.concat([index_definitions, pd.DataFrame({ 'Table Name': [table_name], 'Index Name': [index_name], 'Column Name': [column_name] })], ignore_index=True) # Excelファイルに書き出し(テーブル定義とインデックス情報を別のシートに保存) with pd.ExcelWriter(output_excel) as writer: table_definitions.to_excel(writer, index=False, sheet_name='Table Definitions') index_definitions.to_excel(writer, index=False, sheet_name='Index Definitions') # 接続を閉じる conn.close() print(f"テーブル定義書とインデックス情報を {output_excel} に出力しました。") # データベースファイルと出力先Excelファイルを指定して関数を呼び出し generate_table_definitions_with_indexes('demo.db', 'table_definitions.xlsx') # lib_log_manager.py import logging from logging.handlers import RotatingFileHandler class LogManager: @staticmethod def setup_logging(log_file='application.log', level=logging.INFO): """ ログシステムの初期設定を行います。 :param log_file: ログファイルの名前 :param level: ログレベル """ log_format = '%(asctime)s - %(levelname)s - %(message)s' logging.basicConfig(level=level, format=log_format, datefmt='%Y-%m-%d %H:%M:%S') # ファイル出力を設定 if log_file: try: handler = RotatingFileHandler(log_file, maxBytes=1048576, backupCount=5) handler.setFormatter(logging.Formatter(log_format)) logging.getLogger('').addHandler(handler) except IOError as e: print("Error setting up logging: ", e) @staticmethod def set_log_level(level): """ ログレベルを設定します。 :param level: ログレベル """ logging.getLogger('').setLevel(level) @staticmethod def log_info(message): logging.info(message) @staticmethod def log_error(message, include_traceback=False): if include_traceback: logging.error(message, exc_info=True) else: logging.error(message) @staticmethod def log_warning(message): logging.warning(message)# database_handler.py import sqlite3 import pandas as pd from lib_log_manager import LogManager from utils import get_db_path from config import SQLITE_CONFIG class SqliteHandler: def __init__(self): self.db_file = get_db_path(SQLITE_CONFIG['db_dir'], SQLITE_CONFIG['db_filename']) self.conn = None self.connect_to_database() def connect_to_database(self): try: self.conn = sqlite3.connect(self.db_file) LogManager.log_info("Database connection successfully established.") except sqlite3.Error as e: LogManager.log_error(f"Failed to connect to the database. Error: {e}") # ここでエラーを再発生させるか、あるいは呼び出し元が対応できるように、Falseを返すこともできます。 raise e # エラーを再発生させる場合 # return False # 呼び出し元がエラー4を処理できるようにする場合 def fetch_table_data(self, table_name): query = f"SELECT count(*) FROM {table_name};" cursor = self.conn.cursor() cursor.execute(query) columns = [desc[0] for desc in cursor.description] data = cursor.fetchall() cursor.close() df = pd.DataFrame(data, columns=columns) return df def insert_data_to_table(self, table_name, data): cursor = self.conn.cursor() for _, row in data.iterrows(): placeholders = ','.join(['?'] * len(row)) query = f"INSERT INTO {table_name} VALUES ({placeholders})" cursor.execute(query, tuple(row)) self.conn.commit() cursor.close() def close_connection(self): if self.conn: self.conn.close() # main.py import os from lib_sqlite_handler import SqliteHandler import logging from lib_log_manager import LogManager def main(): try: # データベースハンドラを作成し、データベースに接続 db = SqliteHandler() # ソーステーブルからデータを取得して表示 source_table_name = 't_employees' table_data = db.fetch_table_data(source_table_name) LogManager.log_info("Data from SQLite table:") LogManager.log_info(table_data) # データベースとの接続を閉じる db.close_connection() except Exception as e: print("An error occurred:", e) if __name__ == "__main__": LogManager.setup_logging(log_file='example.log', level=logging.INFO) main() import pytest # test_adjust_ratios_to_100.pyの内容 import sys import os # testsディレクトリからの相対パスでtoolディレクトリへのパスを追加 sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../tool'))) from adjustRatiosTo100.adjust_ratios_to_100 import adjust_ratios # 正常系のテストケース @pytest.mark.parametrize("input_amounts, expected_output", [ ([217, 32, 500], [28.97, 4.27, 66.76]), # 既存の例 ([100, 100, 100], [33.33, 33.33, 33.34]), # 均等な場合 ([0, 0, 1000], [0, 0, 100]), # ゼロが含まれる場合 ([1, 1, 1], [33.33, 33.33, 33.34]), # 小さい値で均等な場合 ([1000], [100]), # 単一の値の場合 ]) def test_adjust_ratios(input_amounts, expected_output): adjusted = adjust_ratios(input_amounts) # 小数点第二位までの比較で許容誤差を考慮 assert all(abs(a - b) < 0.01 for a, b in zip(adjusted, expected_output)) # 合計が100%を超える場合のテストケース(異常系) def test_sum_over_100(): with pytest.raises(ValueError): adjust_ratios([101, 101, 101]) # 入力値が負の場合のテストケース(異常系) def test_negative_values(): with pytest.raises(ValueError): adjust_ratios([-1, 200, 300]) import pytest import os import sys # testsディレクトリからの相対パスでtoolディレクトリへのパスを追加 sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))) from lib_log_manager import LogManager import logging @pytest.fixture def logger(caplog): caplog.set_level(logging.INFO) return caplog def test_setup_logging(caplog): LogManager.setup_logging(log_file='test.log') assert 'Log system initialized successfully.' in caplog.text def test_set_log_level(caplog): LogManager.set_log_level(logging.DEBUG) assert 'Log level set to DEBUG.' in caplog.text def test_log_info(caplog): LogManager.log_info('This is an info message.') assert 'This is an info message.' in caplog.text def test_log_error(caplog): LogManager.log_error('This is an error message.', include_traceback=True) assert 'This is an error message.' in caplog.text def test_log_warning(caplog): LogManager.log_warning('This is a warning message.') assert 'This is a warning message.' in caplog.textimport os def get_db_path(dir_name,db_name): """ 現在のスクリプトのディレクトリからデータベースファイルへの絶対パスを返す。 :param db_name: データベースファイルの名前(例: 'demo.db') :return: データベースファイルへの絶対パス """ current_dir = os.path.dirname(os.path.abspath(__file__)) db_path = os.path.join(current_dir, dir_name, db_name) return db_path