GitHub CopilotがGPT4oベースになって高速化&賢くなったというのでお試ししてみた。
PythonでFlaskアプリの基本形を開発してみる。
Visual Studio Codeだとプラグインを入れてコード補完やインライン・チャットベースでの支援が受けられて、シームレスに開発プロセスにAIを導入出来る。
今回はインラインのチャットで雛形を作ってみる(適当なpyファイル作って、エディタでCtrl+iするとコパイと簡単に話してすぐにコード反映出来る)
プロンプト
sqlalchemyのAccountモデルを作って、モデルは主キーid、文字列型usernameとpassword、日時型のcreatedとupdatedを持つ
createdはレコードが作成された時間を設定するようにして
updatedはレコードが変更された時間を設定するようにしてすべてのカラムはnotnullにして
こうなった
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from sqlalchemy import Column, Integer, String, DateTime, func from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, DateTime, func from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, DateTime, func from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Account(Base): __tablename__ = 'accounts' id = Column(Integer, primary_key=True, nullable=False) username = Column(String, nullable=False) password = Column(String, nullable=False) created = Column(DateTime, default=func.now(), nullable=False) updated = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False) |
お願いするたびimportが湧いたけど少し修正で行ける感じ
次はコントローラ側
プロンプト
Flaskでログイン画面を作って
sqlalchemyでmysqlに接続して、Accountモデルのusernameが変数usernameに、passwordが変数passwordに一致するか確認する処理を追加
AccountのpasswordはMD5処理されている
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
from flask import Flask, render_template, request, redirect from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from .models import Account import hashlib app = Flask(__name__) @app.route('/') def home(): return render_template('login.html') @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] # Add your authentication logic here # For example, you can check if the username and password match a database record # Create a SQLAlchemy engine engine = create_engine('mysql://username:password@localhost/mydatabase') # Create a session factory Session = sessionmaker(bind=engine) # Create a session session = Session() # Verify the password using MD5 hash password_hash = hashlib.md5(password.encode()).hexdigest() # Query the database for the user with the given username and password user = session.query(Account).filter_by(username=username, password=password_hash).first() if user: return redirect('/dashboard') else: return render_template('login.html', error='Invalid username or password') @app.route('/dashboard') def dashboard(): return 'Welcome to the dashboard!' if __name__ == '__main__': app.run(debug=True) |
やっぱり多少修正すれば使えるね
プロンプト一行で10行以上のコードが出来上がって、直して欲しいところを追加で入れていけば基本形完成。 素人だと生成されたコードの意味がわからずエラー起こしたりするし、エラー処理とかは無いから程よくCopilotにお願いするか、手書きで追加するかは必要だけど、定型処理を毎度書くかどっかからコピペするとかよりは効率良い。
リファクタ機能があるから、そっちでお願いすると多少きれいにしてくれる。
モデルのコードをリファクタしてもらうと
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from sqlalchemy import Column, Integer, String, DateTime, func from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Account(Base): __tablename__ = 'accounts' id = Column(Integer, primary_key=True, nullable=False) username = Column(String, nullable=False) password = Column(String, nullable=False) created = Column(DateTime, default=func.now(), nullable=False) updated = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False) |
重複importを綺麗にしてくれた
コントローラ側も綺麗にしてもらおう
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from flask import Flask, render_template, request, redirect from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from models import Account import bcrypt import os app = Flask(__name__) # Load environment variables DATABASE_URL = os.getenv('DATABASE_URL', 'mysql://username:password@localhost/mydatabase') @app.route('/') def home(): return render_template('login.html') @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'].encode('utf-8') # Create a SQLAlchemy engine engine = create_engine(DATABASE_URL) # Create a session factory Session = sessionmaker(bind=engine) # Create a session session = Session() try: # Query the database for the user with the given username user = session.query(Account).filter_by(username=username).first() # Verify the password using bcrypt if user and bcrypt.checkpw(password, user.password.encode('utf-8')): return redirect('/dashboard') else: return render_template('login.html', error='Invalid username or password') finally: # Close the session session.close() @app.route('/dashboard') def dashboard(): return 'Welcome to the dashboard!' if __name__ == '__main__': app.run(debug=True) |
結構になったね。
DB接続を使うところでベタ書きだったDB接続情報がグローバルに持っていかれて全体で使い回せる構成、更に環境変数から取ろうとして、それでも無ければベタ値になってる、サーバレスとかで使いやすい形。 ベタ値は開発環境用とかで使ったり。 初心者コードがべスプラに近づいてる。
更にMD5弱いからbcrypt使うようにしてくれて、セッションもクローズしてくれてる。
けど、try中にreturnがあるからこのときはクローズしない? と思ったら、中でreturnしてもfinallyは実行されるっていう、今更の気付き、Copilot恐ろしい子! 今まで、DB処理部分だけtryでくくってDBに関する処理だけキャッチして、残りは次って書いてたよ・・・
ちなみに、テストコード作ってとかもしてくれる。
逆に既存コードを説明してってのもしてくれるので、引き継ぎとかされてない謎コードメンテのときとかに結構お役立ち。
対象にもよるけど最低でも2~3割早くなる、簡易ツールとかなら倍単位で早くなる感じ。 テストコードでパターンを書くとかいう手間が省けるので、テストするまでもないかなぁみたいなところも数秒でテストコード出来てクオリティアップできそう。
(10)