プロジェクト

全般

プロフィール

ChatGPT生成コード

https://qiita.com/yoshiweb/items/b46de8ca85bb59921f67

aws lambda関数のinvokeをmockするmotoのpythonテストコード


import unittest
from unittest.mock import patch
from moto import mock_lambda
import boto3

class TestLambdaFunction(unittest.TestCase):

    @mock_lambda
    def test_invoke_lambda_function(self):
        # モックされたLambda関数を作成
        lambda_client = boto3.client('lambda', region_name='us-east-1')
        lambda_client.create_function(
            FunctionName='test_function',
            Runtime='python3.8',
            Role='test-role',
            Handler='lambda_function.lambda_handler',
            Code={'ZipFile': b'...'}
        )

        # Lambda関数を呼び出し、モックされたレスポンスを取得
        with patch('lambda_function.lambda_handler') as mock_lambda_handler:
            mock_response = {'statusCode': 200, 'body': 'Mock Response'}
            mock_lambda_handler.return_value = mock_response

            # テスト対象のコードでLambda関数を呼び出す
            result = lambda_client.invoke(FunctionName='test_function')

            # モックされたレスポンスを確認
            self.assertEqual(result['StatusCode'], 200)
            self.assertEqual(result['Payload'].read().decode('utf-8'), 'Mock Response')

if __name__ == '__main__':
    unittest.main()

pytest利用版

import pytest
from moto import mock_lambda
import boto3

@pytest.fixture
def lambda_client():
    with mock_lambda():
        yield boto3.client('lambda', region_name='us-east-1')

def test_invoke_lambda_function(lambda_client):
    # モックされたLambda関数を作成
    lambda_client.create_function(
        FunctionName='test_function',
        Runtime='python3.8',
        Role='test-role',
        Handler='lambda_function.lambda_handler',
        Code={'ZipFile': b'...'}
    )

    # Lambda関数を呼び出し、モックされたレスポンスを取得
    with patch('lambda_function.lambda_handler') as mock_lambda_handler:
        mock_response = {'statusCode': 200, 'body': 'Mock Response'}
        mock_lambda_handler.return_value = mock_response

        # テスト対象のコードでLambda関数を呼び出す
        result = lambda_client.invoke(FunctionName='test_function')

        # モックされたレスポンスを確認
        assert result['StatusCode'] == 200
        assert result['Payload'].read().decode('utf-8') == 'Mock Response'

Pythonでリクエストにタイムアウトを設定し、エラーが発生した場合にリトライを行うコード

import requests
from retrying import retry

# リトライの条件を設定するデコレータ
@retry(stop_max_attempt_number=3, wait_fixed=2000)  # 最大3回のリトライを行い、2秒ごとにリトライを行う
def make_request_with_timeout(url, timeout):
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()  # エラーコードが返ってきた場合は例外を発生させる
        return response
    except (requests.Timeout, requests.ConnectionError) as e:
        print(f"Error: {e}")
        raise  # 例外を再度発生させてリトライを行う

# 使用例
try:
    response = make_request_with_timeout("https://example.com", timeout=5)
    print("Success:", response.text)
except Exception as e:
    print("Failed to make request:", e)

PythonでExponential Backoffをしたかったのでretryingモジュールを調べてみた

import requests

try:
    response = requests.get("https://example.com", timeout=5)
    response.raise_for_status()
    status_code = response.status_code
    print("Success - Status Code:", status_code)
except requests.exceptions.RequestException as e:
    status_code = getattr(e.response, 'status_code', None)
    if status_code:
        print("Error - Status Code:", status_code)
    else:
        print("Error - No status code available")
    print("Error:", e)

JavaScriptを使用してMicrosoft TeamsボットでFileConsentCardを利用してファイルをダウンロードするサンプルコードです。

const { ActionTypes, CardFactory } = require('botbuilder');
const { TeamsInfo } = require('botbuilder-core');

// FileConsentCardを作成する関数
function createFileConsentCard(fileUrl, fileName, fileSize) {
    const consentCard = CardFactory.fileConsentCard(
        {
            description: `You are about to download: ${fileName} (${fileSize} bytes)`,
            sizeInBytes: fileSize,
            acceptContext: { fileUrl, fileName, fileSize },
            declineContext: {}
        }
    );
    return consentCard;
}

// ボットからファイルを送信するメイン関数
async function sendFile(context) {
    const fileUrl = 'https://example.com/sample.pdf'; // ダウンロードするファイルのURL
    const fileName = 'sample.pdf'; // ファイル名
    const fileSize = 1024; // ファイルサイズ(バイト単位)

    const consentCard = createFileConsentCard(fileUrl, fileName, fileSize);
    await context.sendActivity({ attachments: [consentCard] });
}

// ユーザーのファイル承認/拒否のイベントを処理するハンドラー
async function handleFileConsent(context) {
    const reply = context.activity.value;
    if (reply.action === 'accept') {
        // ファイルを承認した場合の処理
        const fileUrl = reply.context.fileUrl;
        // ファイルをダウンロードする処理を実行
        // 例: ダウンロードリンクを送信する
        await context.sendActivity(`You accepted the file download. Here is the download link: ${fileUrl}`);
    } else {
        // ファイルを拒否した場合の処理
        await context.sendActivity('You declined the file download.');
    }
}

// Bot Frameworkのハンドラーを登録
bot.onMessage(async (context, next) => {
    if (context.activity.type === ActionTypes.Message) {
        await sendFile(context);
    }
    await next();
});

bot.onEvent('fileConsent/invoke', async (context, next) => {
    await handleFileConsent(context);
    await next();
});

tmp

const fs = require('fs');
const path = require('path');

// ファイルを保存するディレクトリパスを指定
const saveDirectory = './tmp';

// 保存するファイル名を指定
const fileName = 'example.txt';

// 保存するデータを指定
const fileData = 'This is example file data.';

// ファイルを保存する関数
function saveFileToDisk(data, callback) {
    // ファイルパスを作成
    const filePath = path.join(saveDirectory, fileName);

    // ファイルを書き込み
    fs.writeFile(filePath, data, (err) => {
        if (err) {
            console.error('Error saving file:', err);
            callback(err);
        } else {
            console.log('File saved successfully:', filePath);
            callback(null, filePath);
        }
    });
}

// 保存するファイルを作成
saveFileToDisk(fileData, (err, filePath) => {
    if (err) {
        console.error('Error saving file:', err);
    } else {
        console.log('File saved successfully:', filePath);
    }
});
const { CardFactory } = require('botbuilder');

// Adaptive CardのJSONデータ
const cardData = {
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "TextBlock",
            "text": "Hello, Adaptive Card!",
            "size": "large",
            "weight": "bolder"
        },
        {
            "type": "Image",
            "url": "https://adaptivecards.io/content/adaptive-card-50.png",
            "size": "medium"
        },
        {
            "type": "TextBlock",
            "text": "This is an Adaptive Card.",
            "wrap": true
        }
    ]
};

// Adaptive Cardを作成する
const adaptiveCard = CardFactory.adaptiveCard(cardData);

// このAdaptive Cardを含むメッセージを作成する
const messageWithAdaptiveCard = {
    type: 'message',
    text: 'Here is an Adaptive Card:',
    attachments: [adaptiveCard]
};

async function fetchWithRetry(
  url: string,
  options: RequestInit = {},
  retries: number = 3,
  delay: number = 1000
): Promise<Response> {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);

      if (response.status >= 400) {
        throw new Error(`HTTP Error: ${response.status}`);
      }

      // ステータスコードが400未満の場合は、成功としてレスポンスを返す
      return response;

    } catch (error) {
      if (i < retries - 1) {
        console.warn(`Request failed (attempt ${i + 1}), retrying in ${delay}ms...`);
        await new Promise((resolve) => setTimeout(resolve, delay));
      } else {
        console.error('Max retries reached. Throwing error.');
        throw error;
      }
    }
  }

  throw new Error('Unexpected error');  // ここに到達することはないはずですが、型の安全性のために追加しています
}

// 使用例
(async () => {
  try {
    const response = await fetchWithRetry('https://example.com/api/data', { method: 'GET' });
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Final error after retries:', error);
  }
})();



{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAccessToSpecificBucket",
            "Effect": "Deny",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::test-hidden-774313473161-1",
                "arn:aws:s3:::test-hidden-774313473161-2",
                "arn:aws:s3:::test-hidden-774313473161-1/*",
                "arn:aws:s3:::test-hidden-774313473161-2/*"
            ]
        }
    ]
}
sed ':a;N;$!ba;s/\("[^"]*\)\n\([^"]*"\)/\1 \2/g' input.csv > output.csv
sed ':a; /"$/!{N; s/\n/ /; ba}' input.csv > output.csv
awk '{
  if (match($0, /"$/)) {
    print gensub(/\n/, " ", "g")
  } else {
    printf gensub(/\n/, " ", "g")
  }
}' RS='"' ORS='"' input.csv > output.csv
import React, { useState } from 'react';

const TextAreaComponent: React.FC = () => {
  // useStateフックを使用して、入力値を管理するstateを定義
  const [text, setText] = useState<string>('');

  // textareaの入力値が変更されたときに呼び出される関数
  const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setText(event.target.value);
  };

  return (
    <div>
      <textarea
        value={text}
        onChange={handleChange}
        placeholder="ここにテキストを入力してください"
      />
      <p>入力内容: {text}</p>
    </div>
  );
};

export default TextAreaComponent;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@RestController
@RequestMapping("/api/pdf")
public class PdfController {

    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadPdf(HttpServletResponse response) {
        try {
            // PDF生成 (今回は簡易的に空のPDFファイルを生成)
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            // サンプルのPDFファイルの生成(Apache PDFBoxやiTextなどのライブラリを使用可能)
            // ここでは空のPDFを作成する例
            outputStream.write(new byte[]{ 0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x34 }); // %PDF-1.4

            // ヘッダーを設定してレスポンスに書き込み
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "inline; filename=sample.pdf");
      headers.add("Content-Type", "application/pdf");  // Content-Typeをapplication/pdfに設定

            return ResponseEntity
                    .status(HttpStatus.OK)
                    .headers(headers)
                    .body(outputStream.toByteArray());

        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}
import { visit } from 'unist-util-visit';
import { Root, Text } from 'hast'; // AST の型定義

// 角括弧で囲まれた数式を $...$ に変換する関数
export function rehypeCustomKatex() {
  return (tree: Root) => {
    visit(tree, 'text', (node: Text) => {
      // 角括弧で囲まれた数式を $...$ に変換
      node.value = node.value.replace(/\[([^[\]]+)\]/g, (_, math) => `$${math}$`);
    });
  };
}
// Strategy インターフェース
interface PaymentStrategy {
  pay(amount: number): void;
}

// ConcreteStrategy クラス:クレジットカードで支払う戦略
class CreditCardPayment implements PaymentStrategy {
  private name: string;
  private cardNumber: string;

  constructor(name: string, cardNumber: string) {
    this.name = name;
    this.cardNumber = cardNumber;
  }

  pay(amount: number): void {
    console.log(`Paid ${amount} using Credit Card. Name: ${this.name}, Card Number: ${this.cardNumber}`);
  }
}

// ConcreteStrategy クラス:PayPalで支払う戦略
class PayPalPayment implements PaymentStrategy {
  private email: string;

  constructor(email: string) {
    this.email = email;
  }

  pay(amount: number): void {
    console.log(`Paid ${amount} using PayPal. Email: ${this.email}`);
  }
}

// Context クラス:支払い方法を保持し、操作する
class PaymentContext {
  private strategy: PaymentStrategy;

  constructor(strategy: PaymentStrategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy: PaymentStrategy): void {
    this.strategy = strategy;
  }

  processPayment(amount: number): void {
    this.strategy.pay(amount);
  }
}

// クライアントコード
const creditCardPayment = new CreditCardPayment("John Doe", "1234-5678-9012-3456");
const payPalPayment = new PayPalPayment("john.doe@example.com");

const paymentContext = new PaymentContext(creditCardPayment);
paymentContext.processPayment(100); // クレジットカードで支払い

paymentContext.setStrategy(payPalPayment);
paymentContext.processPayment(200); // PayPalで支払い

const str = "[123]";
const regex = /\[(\d+)\]/;

const match = str.match(regex);
if (match) {
  console.log(match[1]); // "123" (括弧内の数値にアクセス)
}
type Item = { id: number; name: string };

const array: Item[] = [
  { id: 1, name: "xxx" },
  { id: 2, name: "yyy" },
];

const dictionary = array.reduce((acc, item) => {
  acc[item.id] = item;
  return acc;
}, {} as { [key: number]: Item });

console.log(dictionary);
package com.example.demo;

import java.net.URL;
import java.nio.file.Paths;

public class Main {

    public static void main(String[] args) throws Exception {

        URL resourceUrl = Main.class.getProtectionDomain().getCodeSource().getLocation();
        String absolutePath = Paths.get(resourceUrl.toURI()).toAbsolutePath().toString();

        System.out.println("絶対パス: " + absolutePath);
    }

}

import React, { useState } from "react";
import pako from "pako";

const GzipComponent: React.FC = () => {
  const [inputText, setInputText] = useState<string>("");
  const [compressedData, setCompressedData] = useState<string>("");
  const [decompressedText, setDecompressedText] = useState<string>("");

  // Gzip圧縮
  const handleCompress = () => {
    try {
      const binaryData = new TextEncoder().encode(inputText); // 文字列をバイナリに変換
      const compressed = pako.gzip(binaryData); // Gzip圧縮
      setCompressedData(Buffer.from(compressed).toString("base64")); // Base64エンコード
    } catch (error) {
      console.error("圧縮エラー:", error);
    }
  };

  // Gzip解凍
  const handleDecompress = () => {
    try {
      const binaryData = Buffer.from(compressedData, "base64"); // Base64デコード
      const decompressed = pako.ungzip(binaryData, { to: "string" }); // Gzip解凍
      setDecompressedText(decompressed);
    } catch (error) {
      console.error("解凍エラー:", error);
    }
  };

  return (
    <div style={{ padding: "20px", maxWidth: "600px", margin: "auto" }}>
      <h2>Gzip 圧縮・解凍デモ</h2>

      <textarea
        value={inputText}
        onChange={(e) => setInputText(e.target.value)}
        placeholder="ここにテキストを入力"
        rows={4}
        style={{ width: "100%" }}
      />

      <button onClick={handleCompress} style={{ margin: "10px" }}>
        圧縮
      </button>
      <button onClick={handleDecompress} disabled={!compressedData}>
        解凍
      </button>

      <h3>圧縮データ(Base64):</h3>
      <textarea readOnly value={compressedData} rows={4} style={{ width: "100%" }} />

      <h3>解凍後のテキスト:</h3>
      <textarea readOnly value={decompressedText} rows={4} style={{ width: "100%" }} />
    </div>
  );
};

export default GzipComponent;
function sortByKeyDesc(array, key) {
    return [...array].sort((a, b) => (b[key] > a[key] ? 1 : -1));
}

// 使用例
const data = [
    { name: "Alice", age: 25 },
    { name: "Bob", age: 30 },
    { name: "Charlie", age: 22 }
];

const sortedData = sortByKeyDesc(data, "age");

console.log(sortedData);
// 出力: [ { name: 'Bob', age: 30 }, { name: 'Alice', age: 25 }, { name: 'Charlie', age: 22 } ]

function formatUnixTime(unixTime: number): string {
    // Unixタイムが秒単位の場合、ミリ秒に変換
    if (unixTime < 1e10) {
        unixTime *= 1000;
    }

    const date = new Date(unixTime);

    // フォーマットされた日付文字列を生成
    const formattedDate = date.toLocaleString("ja-JP", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        hour12: false,
    });

    // `yyyy/MM/dd HH:mm` 形式になっているので、`-` に置換
    return formattedDate.replace(/\//g, "-").replace(" ", " ");
}

// テスト
const unixTime = 1710514800; // 例: 2024-03-15 12:00 UTC (秒単位)
console.log(formatUnixTime(unixTime)); // 2024-03-15 21:00(日本時間)