├── .github ├── ISSUE_TEMPLATE │ ├── sweep-bugfix.yml │ ├── sweep-feature.yml │ └── sweep-refactor.yml └── workflows │ ├── on-new-issue.yml │ └── pr-agent.yaml ├── .gitignore ├── .pr_agent.toml ├── README.md ├── examples ├── README.md ├── __init__.py ├── bank_account │ ├── _.codiumai.toml │ ├── __init__.py │ ├── bank_account.py │ └── bank_account_modified.py ├── bank_account_2 │ ├── README.md │ ├── __init__.py │ ├── bank_account_2.py │ ├── bank_account_2_modified.py │ ├── bank_account_2_with_included_tests.py │ ├── test_bank_account.py │ ├── test_bank_account_free_functions.py │ └── test_bank_account_unittest.py ├── bank_account_3_context_games │ ├── README.md │ ├── __init__.py │ ├── bank_account_3.py │ ├── bank_account_3_helpers.py │ ├── test_bank_account_3.py │ └── test_bank_account_3_free_functions.py ├── bulleted_list │ ├── __init__.py │ ├── parse_bulleted_list.py │ ├── parse_bulleted_list_modified.py │ └── test_parse_bulleted_list.py ├── client_age_generation │ ├── __init__.py │ ├── client_age_generation.py │ └── test_client_age_generation.py ├── example.svg ├── library │ ├── __init__.py │ └── library.py ├── library_2 │ ├── __init__.py │ ├── book_2.py │ ├── library_2.py │ ├── random_data_gen.py │ └── test_library_2.py ├── library_3 │ ├── __init__.py │ ├── active_borrow.py │ ├── admin.py │ ├── admin_management.py │ ├── admin_management_factory.py │ ├── audit_log.py │ ├── audit_log_db.py │ ├── book_borrowing_db.py │ ├── book_info.py │ ├── book_inventory_listing.py │ ├── book_listing.py │ ├── copy_of_test_library.py │ ├── in_memory_library_book_db.py │ ├── in_memory_user_db.py │ ├── librarian.py │ ├── librarian_book_management.py │ ├── librarian_book_management_factory.py │ ├── library_3.py │ ├── library_factory.py │ ├── member.py │ ├── member_book_management.py │ ├── member_book_management_factory.py │ ├── permissions.py │ ├── test_library.py │ ├── user.py │ ├── user_book_management.py │ └── user_management.py ├── quick_sort │ ├── __init__.py │ ├── quick_sort.py │ └── test_quick_sort.py ├── user.sql └── yaml_strip │ ├── __init__.py │ ├── test_yaml_strip.py │ └── yaml_strip.py ├── media └── docs │ ├── Closedalphabanner.png │ ├── Generatetests013_org_long.gif │ ├── GeneratetestsV2.gif │ ├── Joincommunity.png │ ├── Step1.png │ ├── Step2.png │ ├── Step3.png │ ├── Step4.png │ ├── Step5.png │ ├── Step6.png │ ├── Step7.png │ ├── Step8.png │ ├── TestGeneration.gif │ ├── Tip1.png │ ├── auth1.png │ ├── auth2.png │ ├── auth3.png │ ├── auth4.png │ ├── generateButtons.png │ ├── installed.png │ ├── signin.png │ └── uninstallS1.png └── requirements.txt /.github/ISSUE_TEMPLATE/sweep-bugfix.yml: -------------------------------------------------------------------------------- 1 | name: Bugfix 2 | title: 'Sweep: ' 3 | description: Write something like "We notice ... behavior when ... happens instead of ..."" 4 | labels: sweep 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Details 10 | description: More details about the bug 11 | placeholder: The bug might be in ... file -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/sweep-feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | title: 'Sweep: ' 3 | description: Write something like "Write an api endpoint that does "..." in the "..." file" 4 | labels: sweep 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Details 10 | description: More details for Sweep 11 | placeholder: The new endpoint should use the ... class from ... file because it contains ... logic -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/sweep-refactor.yml: -------------------------------------------------------------------------------- 1 | name: Refactor 2 | title: 'Sweep: ' 3 | description: Write something like "Modify the ... api endpoint to use ... version and ... framework" 4 | labels: sweep 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Details 10 | description: More details for Sweep 11 | placeholder: We are migrating this function to ... version because ... -------------------------------------------------------------------------------- /.github/workflows/on-new-issue.yml: -------------------------------------------------------------------------------- 1 | name: Run pr agent on every opened issue, respond to user comments on an issue 2 | 3 | #When the action is triggered 4 | on: 5 | issues: 6 | types: [opened] #New issue 7 | 8 | # Read env. variables 9 | env: 10 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 11 | GITHUB_API_URL: ${{ github.api_url }} 12 | GIT_REPO_URL: ${{ github.event.repository.clone_url }} 13 | ISSUE_URL: ${{ github.event.issue.html_url || github.event.comment.html_url }} 14 | ISSUE_BODY: ${{ github.event.issue.body || github.event.comment.body }} 15 | OPENAI_KEY: ${{ secrets.OPENAI_KEY }} 16 | 17 | # The actual set of actions 18 | jobs: 19 | issue_agent: 20 | runs-on: ubuntu-latest 21 | if: ${{ github.event.sender.type != 'Bot' }} 22 | 23 | # Set required permissions 24 | permissions: 25 | contents: read # For reading repository contents 26 | issues: write # For commenting on issues 27 | 28 | steps: 29 | - name: Run PR Agent on Issues 30 | if: ${{ env.ISSUE_URL != '' }} 31 | uses: docker://codiumai/pr-agent:latest 32 | with: 33 | entrypoint: /bin/bash #Replace invoking cli.py directly with a shell 34 | args: | 35 | -c "cd /app && \ 36 | echo 'Running Issue Agent action step on ISSUE_URL=$ISSUE_URL' && \ 37 | export config__git_provider='github' && \ 38 | export github__user_token=$GITHUB_TOKEN && \ 39 | export github__base_url=$GITHUB_API_URL && \ 40 | export openai__key=$OPENAI_KEY && \ 41 | export config__verbosity_level=2 && \ 42 | python -m pr_agent.cli --issue_url=$ISSUE_URL help_docs --pr_help_docs.repo_url=https://github.com/qodo-ai/pr-agent.git \"$ISSUE_BODY\"" 43 | 44 | -------------------------------------------------------------------------------- /.github/workflows/pr-agent.yaml: -------------------------------------------------------------------------------- 1 | name: Qode Merge PR-Agent (OpenAI) 2 | 3 | on: 4 | pull_request: 5 | types: [ opened, reopened, ready_for_review ] 6 | issue_comment: 7 | jobs: 8 | pr_agent_job: 9 | if: ${{ github.event.sender.type != 'Bot' }} 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | contents: write 15 | name: Run pr agent on every pull request, respond to user comments 16 | steps: 17 | - name: PR Agent action step 18 | id: pragent 19 | uses: Codium-ai/pr-agent@main 20 | env: 21 | OPENAI_KEY: ${{ secrets.OPENAI_KEY }} 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | github_action_config.auto_review: "true" # enable\disable auto review 24 | github_action_config.auto_describe: "true" # enable\disable auto describe 25 | github_action_config.auto_improve: "true" # enable\disable auto improve 26 | github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "review_requested"]' 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | env/ 4 | 5 | # Compiled python modules. 6 | *.pyc 7 | 8 | # Setuptools distribution folder. 9 | /dist/ 10 | /build/ 11 | 12 | # Python egg metadata, regenerated from source files by setuptools. 13 | /*.egg-info 14 | /*.egg 15 | 16 | 17 | __pycache__ 18 | 19 | .idea 20 | .hypothesis 21 | .testmondata 22 | 23 | .vscode 24 | 25 | .coverage 26 | .env 27 | 28 | # pyenv 29 | .python-version 30 | -------------------------------------------------------------------------------- /.pr_agent.toml: -------------------------------------------------------------------------------- 1 | 2 | [pr_reviewer] 3 | extra_instructions = "" 4 | enable_review_labels_security = false 5 | enable_review_labels_effort = false 6 | require_can_be_split_review = true 7 | enable_auto_approval = true 8 | maximal_review_effort = 1 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodiumAI - Meaningful tests for busy devs 2 | 3 | [![Closed Alpha](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Closedalphabanner.png)](https://www.codium.ai/#Contact-us) 4 | 5 | --- 6 | 7 | > CodiumAI analyzes your Python code and generates meaningful tests to catch bugs before you ship. With Codium, you can easily and quickly create comprehensive test suites that help you ensure the reliability and correctness of your software. 8 | 9 | --- 10 | 11 | ![How it works](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Generatetests013_org_long.gif) 12 | 13 | _Closed Alpha Version 1.0.0 - Supported in VSCode version 1.58.0 and above_ 14 | 15 | ## Features 16 | 17 | #### 🤖 Generates unit tests automatically 18 | 19 | Simply press the "generate tests" button above your Python class or function, and CodiumAI will generate a set of suggested tests for different use cases. 20 | 21 | #### ✨ Works seamlessly with VSCode 22 | 23 | The generated tests will be displayed in a new tab in your VSCode IDE, along with your code description, so you can easily review and edit them as needed. 24 | 25 | #### 🚀 Helps you improve code quality 26 | 27 | By creating comprehensive test suites, our tool helps you catch and fix bugs early, and ensures that your code is reliable and maintainable. 28 | 29 | --- 30 | 31 | ## Installing / Getting started 32 | 33 | ![Install](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step1.png) 34 |
35 | 36 | ![Successful installation](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step2.png) 37 |
38 | 39 | ![Github Login page step one](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step3.png) 40 |
41 | 42 | ![Github Login page step two](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step4.png) 43 |
44 | 45 | ![Generate tests](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step5.png) 46 |
47 | 48 | ![Codium tab opens](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step6.png) 49 |
50 | 51 | ![Review and edit samples](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step7.png) 52 |
53 | 54 | ![Redo tests](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Step8.png) 55 |
56 | 57 | 1. After installation, you should receive a notification on the bottom of the VSCode editor. Click "Sign in" button in the notification popup to activate Codium with your GitHub account. 58 | 59 | > If you can't see the notification on the bottom right of the editor window, click the button labeled Codium in the bottom status bar. 60 | 61 | 2. You will be redirected to the GitHub login page. 62 | 63 | 3. Once you confirm the activation you should be redirected back to the editor. Status notification should show your GitHub username when the activation was successful. 64 | 65 | 4. Open existing Python file or write a new Python class/function and press the "Generate Tests" on top of the class/function. 66 | 67 | 5. A new tab will open in your VSCode IDE with the generated tests, along with your code description and test strategies description. 68 | 69 | 6. Review tests and edit tests strategies to improve the quality of the next tests generation. 70 | 71 | 7. Use "Redo tests" to refine your tests according to your edits. 72 | 73 | 8. "Accept" to add the generated tests to a new file. 74 | 75 | > Tip 1: If you can't see the `Generate Tests` button you might have to set `"editor.codeLens": true,` in your VSCode configuration file. 76 | > Tip 2: You can show and hide Codium panel in the extension settings or from the command palette. 77 | 78 | ![Tip show panel](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Tip1.png) 79 |
80 | 81 | ## How to uninstall 82 | 83 | 1. Select "Codium" button in the bottom status bar. 84 | 2. Hover over the authentication notification, select the settings icon and "Manage Extension" option from the dropdown. 85 | 3. Codium Extension will open in a new tab. Select Uninstall and Reload VSCode. 86 | 87 | ## Links 88 | 89 | [![Join our Discord community](https://raw.githubusercontent.com/Codium-ai/codium-code-examples/main/media/docs/Joincommunity.png)](https://discord.gg/TqNxGqFW) 90 | 91 | - Discord community: https://discord.gg/TqNxGqFW 92 | - Code examples: https://github.com/Codium-ai/codium-code-examples 93 | - Project homepage: https://codium.ai 94 | - Blog: https://www.codium.ai/blog 95 | 96 | ## Terms of use 97 | 98 | - Terms of use: https://www.codium.ai/terms-of-use 99 | - Privacy policy: https://www.codium.ai/platform-privacy-policy 100 | - Please notice - similar to other popular generative-AI tools (such as copilot), we also transmit code snippets to our servers. 101 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Codium code examples 2 | These are code examples intended for serving as reference while evaluating Codium. 3 | 4 | # What to test 5 | Try creating tests for these files: 6 | ``` 7 | examples/bank_account/bank_account.py 8 | examples/colors/colors.py 9 | examples/library/library.py 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/__init__.py -------------------------------------------------------------------------------- /examples/bank_account/_.codiumai.toml: -------------------------------------------------------------------------------- 1 | [tests] 2 | 3 | ## Testing framework to use - this can affect the content of the generated tests 4 | ## as well as the test run command. 5 | ## Possible values are: 6 | ## Python: Pytest, Unittest 7 | ## Javascript / Typescript: Jest, Mocha, Vitest, Karma, Jasmine, QUnit, React Testing Library 8 | ## HOWEVER: running tests in JS / TS is at the moment only supported 9 | ## for Jest, Mocha, Vitest, and React Testing Library 10 | # framework = "Mocha" 11 | 12 | ## An additional Javascript utility library used to test your code, if any. 13 | ## Possible values are None, Testing Library, Enzyme, or Chai. Not applicable to Python projects. 14 | # utility_library = "Chai" 15 | 16 | ## A hint to the test generator about whether to use mocks or not. Possible values are true or false. 17 | # use_mocks = false 18 | 19 | ## How many tests should be generated by default. Fewer tests is faster. 20 | ## Does not apply at the moment to extend-suite tests. 21 | # num_desired_tests = 2 22 | 23 | 24 | ## A multiline string, delimited with triple-quotes (""") serving as an example test that represents 25 | ## what you would like the generated tests to look like in terms of style, setup, etc. 26 | reference_test = """ 27 | 28 | 29 | def test_deposit_positive_amount(self): 30 | # Always use lord of the rings characters for testing 31 | account = BankAccount("Gandalf", True) 32 | initial_balance = account.balance() 33 | account.deposit(100) 34 | assert account.balance() == initial_balance + 97.5 35 | 36 | 37 | """ 38 | 39 | 40 | [tests.javascript] 41 | 42 | ## When running Javascript / Typescript tests, use this directory as the test process "current working directory". 43 | ## This is a path relative to the location of the config file. 44 | ## Default: The directory containing the config file. 45 | ## Note: the typical setup is to place the config file in the same directory as the relevant `package.json` file, 46 | ## and leave this commented-out. 47 | # overrideTestRunCwd = "./test" 48 | 49 | ## This is the command that's used to run tests. 50 | ## PLEASE READ CAREFULLY: 51 | ## 52 | ## When running tests, CodiumAI generates a temporary file that contains the test code for a single test, 53 | ## and runs that file. 54 | ## When the tests are done, the temporary file is deleted. 55 | ## For component-oriented tests (when you click "test this class" or "test this function"), the temporary file 56 | ## is created next to the file being tested. 57 | ## For extend-suite tests (when you click "add more tests" on a test-suite), the temporary file is created next 58 | ## to the test-suite file. 59 | ## 60 | ## Typically, you're going to want to take the test script defined in your package.json file, and tweak it a 61 | ## little to make it compatible with CodiumAI. 62 | ## 63 | ## You almost always want to start with 'npx' (e.g. 'npx jest', not 'npm jest' or 'yarn test'). 64 | ## 65 | ## Note that the test command must be able to run test files that are located in the same directory as the 66 | ## file under test. 67 | ## A common issue is that the test command in the package.json file selects only from 68 | ## a "tests" directory, causing the CodiumAI tests be "not found" - please remove any such restriction from 69 | ## the command / configuration. 70 | ## 71 | ## The placeholder TEST_FILEPATH will be replaced with the actual test file path - this is how we find 72 | ## the file to run. 73 | ## 74 | ## EXAMPLES: 75 | ## Mocha: 76 | ## npx ts-mocha TEST_FILEPATH --require ./test/mocha/setup.ts 77 | ## Jest: 78 | ## npx jest --runTestsByPath TEST_FILEPATH 79 | ## 80 | ## DEBUGGING NOTE: 81 | ## To help debug run-tests issues, you can view run logs in vscode's OUTPUT 82 | ## (select codium-ai from the dropdown). 83 | ## It's helpful to clear the output (right-click -> clear) and then run the tests again. 84 | ## 85 | # overrideTestRunScript = "npx jest --runTestsByPath TEST_FILEPATH" 86 | 87 | ## A multiline string, delimited with triple-quotes ("""), 88 | ## containing import declarations that will be added at the beginning to each test file. 89 | # overrideImports = """ 90 | # import {expect} from 'chai'; """ -------------------------------------------------------------------------------- /examples/bank_account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/bank_account/__init__.py -------------------------------------------------------------------------------- /examples/bank_account/bank_account.py: -------------------------------------------------------------------------------- 1 | class BankAccount: 2 | """ Create a new bank account """ 3 | def __init__(self, name, hasCommissionDiscount): 4 | self._name = name 5 | self._hasCommissionDiscount = hasCommissionDiscount 6 | self._balance = 0 7 | self._commission_rate = BankAccount._calc_commission_rate(hasCommissionDiscount) 8 | 9 | def info(self): 10 | """ Account information """ 11 | return { 12 | "name": self._name, 13 | "current_balance": self._balance, 14 | } 15 | 16 | def deposit(self, amount): 17 | """ deposit money """ 18 | if amount > 0: 19 | self._balance -= amount - self._calc_commission_rate(self._hasCommissionDiscount) 20 | else: 21 | raise ValueError("deposit amount must be larger than 0") 22 | 23 | def balance(self): 24 | return self._balance 25 | 26 | def withdraw(self, amount): 27 | """ withdraw money """ 28 | if self._balance >= amount > 0: 29 | self._balance += (amount + self._calc_commission_rate(self._hasCommissionDiscount)) 30 | else: 31 | raise ValueError("Insufficient funds for withdraw") 32 | 33 | def transfer_to_other_account(self, amount, other_account): 34 | """ transfer money """ 35 | if amount <= 0: 36 | raise ValueError("Transfer amount must be larger than 0") 37 | amount_including_commission = amount + self._commission_rate 38 | if self._balance >= amount_including_commission > 0: 39 | self._balance -= amount_including_commission 40 | other_account._balance += amount 41 | else: 42 | raise ValueError("Insufficient funds for transfer") 43 | 44 | @staticmethod 45 | def _calc_commission_rate(hasCommisionDiscount): 46 | """ Get the rate of commission for this account """ 47 | if hasCommisionDiscount: 48 | return 2.5 49 | else: 50 | return 5 51 | -------------------------------------------------------------------------------- /examples/bank_account/bank_account_modified.py: -------------------------------------------------------------------------------- 1 | class BankAccount: 2 | """ Create a new bank account """ 3 | def __init__(self, name, hasCommissionDiscount): 4 | self._name = name 5 | self._hasCommissionDiscount = hasCommissionDiscount 6 | self._balance = 0 7 | self._commission_rate = BankAccount._calc_commission_rate(hasCommissionDiscount) 8 | 9 | def info(self): 10 | """ Account information """ 11 | return { 12 | "name": self._name, 13 | "current_balance": self._balance, 14 | } 15 | 16 | def deposit(self, amount): 17 | """ deposit money """ 18 | if amount > 0: 19 | self._balance += amount - self._calc_commission_rate(self._hasCommissionDiscount) 20 | else: 21 | raise ValueError("deposit amount must be larger than 0") 22 | 23 | def balance(self): 24 | return self._balance 25 | 26 | def withdraw(self, amount): 27 | """ withdraw money """ 28 | if self._balance >= amount > 0: 29 | self._balance -= (amount + self._calc_commission_rate(self._hasCommissionDiscount)) 30 | else: 31 | raise ValueError("Insufficient funds for withdraw") 32 | 33 | def can_withdraw(self, amount): 34 | return self._balance >= amount > 0 35 | 36 | def transfer_to_other_account(self, amount, other_account): 37 | """ transfer money """ 38 | if amount <= 0: 39 | raise ValueError("Transfer amount must be larger than 0") 40 | amount_including_commission = amount + self._commission_rate 41 | if self._balance >= amount_including_commission > 0: 42 | self._balance -= amount_including_commission 43 | other_account._balance += amount 44 | else: 45 | raise ValueError("Insufficient funds for transfer") 46 | 47 | @staticmethod 48 | def _calc_commission_rate(hasCommisionDiscount): 49 | """ Get the rate of commission for this account """ 50 | if hasCommisionDiscount: 51 | return 2.5 52 | else: 53 | return 9 54 | -------------------------------------------------------------------------------- /examples/bank_account_2/README.md: -------------------------------------------------------------------------------- 1 | # Why another bank_account example? 2 | Because for demoing component-oriented tests, we want that test files for the other example won't exist - 3 | but for testing add-test-to-suite we do need them. -------------------------------------------------------------------------------- /examples/bank_account_2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/bank_account_2/__init__.py -------------------------------------------------------------------------------- /examples/bank_account_2/bank_account_2.py: -------------------------------------------------------------------------------- 1 | class BankAccount2: 2 | """ Create a new bank account """ 3 | def __init__(self, name, hasCommissionDiscount): 4 | self._name = name 5 | self._hasCommissionDiscount = hasCommissionDiscount 6 | self._balance = 0 7 | self._commission_rate = BankAccount2._calc_commission_rate(hasCommissionDiscount) 8 | 9 | def info(self): 10 | """ Account information """ 11 | return { 12 | "name": self._name, 13 | "current_balance": self._balance, 14 | } 15 | 16 | def deposit(self, amount): 17 | """ deposit money """ 18 | if amount > 0: 19 | self._balance += amount - self._calc_commission_rate(self._hasCommissionDiscount) 20 | else: 21 | raise ValueError("deposit amount must be larger than 0") 22 | 23 | def balance(self): 24 | return self._balance 25 | 26 | def withdraw(self, amount): 27 | """ withdraw money """ 28 | if self._balance >= amount > 0: 29 | self._balance -= (amount + self._calc_commission_rate(self._hasCommissionDiscount)) 30 | else: 31 | raise ValueError("Insufficient funds for withdraw") 32 | 33 | def transfer_to_other_account(self, amount, other_account): 34 | """ transfer money """ 35 | if amount <= 0: 36 | raise ValueError("Transfer amount must be larger than 0") 37 | amount_including_commission = amount + self._commission_rate 38 | if self._balance >= amount_including_commission > 0: 39 | self._balance -= amount_including_commission 40 | other_account._balance += amount 41 | else: 42 | raise ValueError("Insufficient funds for transfer") 43 | 44 | @staticmethod 45 | def _calc_commission_rate(hasCommisionDiscount): 46 | """ Get the rate of commission for this account """ 47 | if hasCommisionDiscount: 48 | return 2.5 49 | else: 50 | return 5 51 | -------------------------------------------------------------------------------- /examples/bank_account_2/bank_account_2_modified.py: -------------------------------------------------------------------------------- 1 | class BankAccount2: 2 | """ Create a new bank account """ 3 | def __init__(self, name, hasCommissionDiscount): 4 | self._name = name 5 | self._hasCommissionDiscount = hasCommissionDiscount 6 | self._balance = 0 7 | self._commission_rate = BankAccount2._calc_commission_rate(hasCommissionDiscount) 8 | 9 | def info(self): 10 | """ Account information """ 11 | return { 12 | "name": self._name, 13 | "current_balance": self._balance, 14 | } 15 | 16 | def deposit(self, amount): 17 | """ deposit money """ 18 | if amount > 0: 19 | self._balance += amount - self._calc_commission_rate(self._hasCommissionDiscount) 20 | else: 21 | raise ValueError("deposit amount must be larger than 0") 22 | 23 | def balance(self): 24 | return self._balance 25 | 26 | def withdraw(self, amount): 27 | """ withdraw money """ 28 | if self._balance >= amount > 0: 29 | self._balance -= (amount + self._calc_commission_rate(self._hasCommissionDiscount)) 30 | else: 31 | raise ValueError("Insufficient funds for withdraw") 32 | 33 | def can_withdraw(self, amount): 34 | return self._balance >= amount > 0 35 | 36 | def transfer_to_other_account(self, amount, other_account): 37 | """ transfer money """ 38 | if amount <= 0: 39 | raise ValueError("Transfer amount must be larger than 0") 40 | amount_including_commission = amount + self._commission_rate 41 | if self._balance >= amount_including_commission > 0: 42 | self._balance -= amount_including_commission 43 | other_account._balance += amount 44 | else: 45 | raise ValueError("Insufficient funds for transfer") 46 | 47 | @staticmethod 48 | def _calc_commission_rate(hasCommisionDiscount): 49 | """ Get the rate of commission for this account """ 50 | if hasCommisionDiscount: 51 | return 2.5 52 | else: 53 | return 9 54 | -------------------------------------------------------------------------------- /examples/bank_account_2/bank_account_2_with_included_tests.py: -------------------------------------------------------------------------------- 1 | class BankAccount2: 2 | """ Create a new bank account """ 3 | def __init__(self, name, hasCommissionDiscount): 4 | self._name = name 5 | self._hasCommissionDiscount = hasCommissionDiscount 6 | self._balance = 0 7 | self._commission_rate = BankAccount2._calc_commission_rate(hasCommissionDiscount) 8 | 9 | def info(self): 10 | """ Account information """ 11 | return { 12 | "name": self._name, 13 | "current_balance": self._balance, 14 | } 15 | 16 | def deposit(self, amount): 17 | """ deposit money """ 18 | if amount > 0: 19 | self._balance += amount - self._calc_commission_rate(self._hasCommissionDiscount) 20 | else: 21 | raise ValueError("deposit amount must be larger than 0") 22 | 23 | def balance(self): 24 | return self._balance 25 | 26 | def withdraw(self, amount): 27 | """ withdraw money """ 28 | if self._balance >= amount > 0: 29 | self._balance -= (amount + self._calc_commission_rate(self._hasCommissionDiscount)) 30 | else: 31 | raise ValueError("Insufficient funds for withdraw") 32 | 33 | def transfer_to_other_account(self, amount, other_account): 34 | """ transfer money """ 35 | if amount <= 0: 36 | raise ValueError("Transfer amount must be larger than 0") 37 | amount_including_commission = amount + self._commission_rate 38 | if self._balance >= amount_including_commission > 0: 39 | self._balance -= amount_including_commission 40 | other_account._balance += amount 41 | else: 42 | raise ValueError("Insufficient funds for transfer") 43 | 44 | @staticmethod 45 | def _calc_commission_rate(hasCommisionDiscount): 46 | """ Get the rate of commission for this account """ 47 | if hasCommisionDiscount: 48 | return 2.5 49 | else: 50 | return 5 51 | 52 | 53 | def test_deposit_positive_amount(): 54 | gandalf = BankAccount2("Gandalf", True) 55 | initial_balance = gandalf.balance() 56 | gandalf.deposit(100) 57 | assert gandalf.balance() == initial_balance + 97.5 58 | 59 | def test_withdraw_positive_amount(): 60 | frodo = BankAccount2("Frodo", True) 61 | frodo.deposit(100) 62 | initial_balance = frodo.balance() 63 | frodo.withdraw(50) 64 | assert frodo.balance() == initial_balance - 52.5 65 | 66 | def test_withdraw_more_than_balance(): 67 | gandalf = BankAccount2("Gandalf", True) 68 | gandalf.deposit(100) 69 | with pytest.raises(ValueError): 70 | gandalf.withdraw(150) 71 | 72 | # Cannot transfer a negative amount from one bank account to another 73 | def test_transfer_negative_amount(): 74 | gandalf = BankAccount2("Gandalf", True) 75 | aragorn = BankAccount2("Aragorn", False) 76 | gandalf.deposit(200) 77 | with pytest.raises(ValueError): 78 | gandalf.transfer_to_other_account(-100, aragorn) 79 | 80 | # Can transfer a positive amount from one bank account to another 81 | def test_transfer_positive_amount(): 82 | frodo = BankAccount2("Frodo", True) 83 | gandalf = BankAccount2("Gandalf", False) 84 | frodo.deposit(200) 85 | gandalf.deposit(0) 86 | initial_frodo_balance = frodo.balance() 87 | initial_gandalf_balance = gandalf.balance() 88 | frodo.transfer_to_other_account(100, gandalf) 89 | assert frodo.balance() == initial_frodo_balance - 102.5 90 | assert gandalf.balance() == initial_gandalf_balance + 100 91 | 92 | # Cannot deposit a negative amount into the bank account 93 | def test_deposit_negative_amount(): 94 | gandalf = BankAccount2("Gandalf", True) 95 | with pytest.raises(ValueError): 96 | gandalf.deposit(-50) 97 | 98 | # Cannot withdraw a negative amount from the bank account 99 | def test_withdraw_negative_amount(): 100 | frodo = BankAccount2("Frodo", True) 101 | frodo.deposit(100) 102 | with pytest.raises(ValueError): 103 | frodo.withdraw(-50) 104 | 105 | 106 | -------------------------------------------------------------------------------- /examples/bank_account_2/test_bank_account.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from examples.bank_account_2.bank_account_2 import BankAccount2 4 | 5 | class TestBankAccount2: 6 | def setup_method(self): 7 | self.account1 = BankAccount2("John", True) 8 | self.account2 = BankAccount2("Jane", False) 9 | 10 | # Tests that depositing a positive amount increases the account balance. 11 | def test_deposit_positive_amount(self): 12 | initial_balance = self.account1.balance() 13 | self.account1.deposit(100) 14 | assert self.account1.balance() == initial_balance + 97.5 15 | 16 | def test_withdraw_positive_amount(self): 17 | self.account1.deposit(100) 18 | initial_balance = self.account1.balance() 19 | self.account1.withdraw(50) 20 | assert self.account1.balance() == initial_balance - 52.5 21 | 22 | def test_withdraw_more_than_balance(self): 23 | self.account1.deposit(100) 24 | with pytest.raises(ValueError): 25 | self.account1.withdraw(150) 26 | 27 | def test_transfer_more_than_balance(self): 28 | self.account1.deposit(100) 29 | with pytest.raises(ValueError): 30 | self.account1.transfer_to_other_account(150, self.account2) 31 | 32 | 33 | def test_transfer_positive_amount(self): 34 | self.account1.deposit(100) 35 | initial_balance1 = self.account1.balance() 36 | initial_balance2 = self.account2.balance() 37 | self.account1.transfer_to_other_account(50, self.account2) 38 | assert self.account1.balance() == initial_balance1 - 52.5 39 | assert self.account2.balance() == initial_balance2 + 50 40 | 41 | 42 | 43 | class TestBankAccountSimpson: 44 | def setup_method(self): 45 | self.homer = BankAccount2("Homer", True) 46 | self.marge = BankAccount2("Marge", False) 47 | 48 | def test_deposit_negative_amount(self): 49 | with pytest.raises(ValueError): 50 | self.homer.deposit(-100) 51 | -------------------------------------------------------------------------------- /examples/bank_account_2/test_bank_account_free_functions.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from examples.bank_account_2.bank_account_2 import BankAccount2 4 | 5 | 6 | def test_deposit_positive_amount(): 7 | gandalf = BankAccount2("Gandalf", True) 8 | initial_balance = gandalf.balance() 9 | gandalf.deposit(100) 10 | assert gandalf.balance() == initial_balance + 97.5 11 | 12 | def test_withdraw_positive_amount(): 13 | frodo = BankAccount2("Frodo", True) 14 | frodo.deposit(100) 15 | initial_balance = frodo.balance() 16 | frodo.withdraw(50) 17 | assert frodo.balance() == initial_balance - 52.5 18 | 19 | def test_withdraw_more_than_balance(): 20 | gandalf = BankAccount2("Gandalf", True) 21 | gandalf.deposit(100) 22 | with pytest.raises(ValueError): 23 | gandalf.withdraw(150) 24 | -------------------------------------------------------------------------------- /examples/bank_account_2/test_bank_account_unittest.py: -------------------------------------------------------------------------------- 1 | 2 | import unittest 3 | 4 | from .bank_account_2 import BankAccount2 5 | 6 | class TestBankAccount(unittest.TestCase): 7 | def setUp(self): 8 | self.account1 = BankAccount2("John", True) 9 | self.account2 = BankAccount2("Jane", False) 10 | 11 | def test_deposit_positive_amount(self): 12 | initial_balance = self.account1.balance() 13 | self.account1.deposit(100) 14 | self.assertEqual(self.account1.balance(), initial_balance + 97.5) 15 | 16 | def test_withdraw_positive_amount(self): 17 | self.account1.deposit(100) 18 | initial_balance = self.account1.balance() 19 | self.account1.withdraw(50) 20 | self.assertEqual(self.account1.balance(), initial_balance - 52.5) 21 | 22 | def test_withdraw_more_than_balance(self): 23 | self.account1.deposit(100) 24 | with self.assertRaises(ValueError): 25 | self.account1.withdraw(150) 26 | 27 | def test_transfer_more_than_balance(self): 28 | self.account1.deposit(100) 29 | with self.assertRaises(ValueError): 30 | self.account1.transfer_to_other_account(150, self.account2) 31 | 32 | def test_transfer_positive_amount(self): 33 | self.account1.deposit(100) 34 | initial_balance1 = self.account1.balance() 35 | initial_balance2 = self.account2.balance() 36 | self.account1.transfer_to_other_account(50, self.account2) 37 | self.assertEqual(self.account1.balance(), initial_balance1 - 52.5) 38 | self.assertEqual(self.account2.balance(), initial_balance2 + 50) 39 | 40 | 41 | if __name__ == '__main__': 42 | unittest.main() 43 | -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/README.md: -------------------------------------------------------------------------------- 1 | # Why another bank_account example? 2 | This is a variation of the bank account, where it was divided to several files, so it won't be as easy to get 3 | the context. 4 | Specifically, it's for testing extend-suite, which currently doesn't know how to bring in context for things that the 5 | CUT uses - so we need to add the context manually. 6 | 7 | The functionality has also been greatly reduced, so we'll always get relevant tests. 8 | Specifically - the premium account has 3 attributes - commision size, max deposit and max balance. 9 | And the values of all these attributes are in the separate file - so no matter what, we'll always 10 | have tests that check for them and have the wrong values if we don't manually add the context. 11 | 12 | There's a top-level-functions test file and a class-test file, so we can test both. 13 | -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/bank_account_3_context_games/__init__.py -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/bank_account_3.py: -------------------------------------------------------------------------------- 1 | from examples.bank_account_3_context_games.bank_account_3_helpers import calc_commission_rate, is_deposit_over_balance, is_more_than_max_deposit 2 | 3 | 4 | class BankAccount3: 5 | """ Create a new bank account """ 6 | def __init__(self, name, is_premium_account): 7 | self._name = name 8 | self._is_premium_account = is_premium_account 9 | self._balance = 0 10 | 11 | def deposit(self, amount): 12 | """ deposit money """ 13 | if amount <= 0: 14 | raise IOError("deposit amount must be larger than 0") 15 | 16 | if is_more_than_max_deposit(self._is_premium_account, amount): 17 | raise ValueError("deposit amount exceeds maximum allowed") 18 | 19 | if is_deposit_over_balance(self._is_premium_account, amount, self._balance): 20 | raise ValueError("deposit amount will exceed maximum allowed balance") 21 | 22 | self._balance += amount - calc_commission_rate(self._is_premium_account) 23 | 24 | def balance(self): 25 | return self._balance 26 | -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/bank_account_3_helpers.py: -------------------------------------------------------------------------------- 1 | MAX_DEPOSIT_PREMIUM = 1_000_000 2 | MAX_DEPOSIT_NON_PREMIUM = 10_000 3 | 4 | MAX_BALANCE_PREMIUM = 10_000_000 5 | MAX_BALANCE_NON_PREMIUM = 100_000 6 | 7 | def calc_commission_rate(is_premium_account): 8 | if is_premium_account: 9 | return 1.5 10 | else: 11 | return 8 12 | 13 | 14 | def is_more_than_max_deposit(is_premium_account, deposit_amount): 15 | if is_premium_account: 16 | return deposit_amount > MAX_DEPOSIT_PREMIUM 17 | else: 18 | return deposit_amount > MAX_DEPOSIT_NON_PREMIUM 19 | 20 | 21 | def is_deposit_over_balance(is_premium_account, deposit_amount, balance): 22 | expected_balance = balance + deposit_amount - calc_commission_rate(is_premium_account) 23 | 24 | if is_premium_account: 25 | return expected_balance > MAX_BALANCE_PREMIUM 26 | else: 27 | return expected_balance > MAX_BALANCE_NON_PREMIUM 28 | -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/test_bank_account_3.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from examples.bank_account_3_context_games.bank_account_3 import BankAccount3 3 | 4 | 5 | class TestBankAccountSimpson: 6 | def setup_method(self): 7 | self.homer = BankAccount3("Homer", True) 8 | self.marge = BankAccount3("Marge", False) 9 | 10 | def test_deposit_with_commission_discount_true(self): 11 | initial_balance = self.homer.balance() 12 | deposit_amount = 100 13 | expected_commission = 1.5 14 | expected_balance = initial_balance + deposit_amount - expected_commission 15 | 16 | self.homer.deposit(deposit_amount) 17 | 18 | assert self.homer.balance() == expected_balance 19 | -------------------------------------------------------------------------------- /examples/bank_account_3_context_games/test_bank_account_3_free_functions.py: -------------------------------------------------------------------------------- 1 | from examples.bank_account_3_context_games.bank_account_3 import BankAccount3 2 | 3 | def test_deposit_with_premium_account_true(): 4 | homer = BankAccount3("Homer", True) 5 | initial_balance = homer.balance() 6 | deposit_amount = 100 7 | expected_commission = 1.5 8 | expected_balance = initial_balance + deposit_amount - expected_commission 9 | 10 | homer.deposit(deposit_amount) 11 | 12 | assert homer.balance() == expected_balance 13 | -------------------------------------------------------------------------------- /examples/bulleted_list/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/bulleted_list/__init__.py -------------------------------------------------------------------------------- /examples/bulleted_list/parse_bulleted_list.py: -------------------------------------------------------------------------------- 1 | from typing import List, Literal, Optional 2 | 3 | 4 | def parse_bullet_list(list_str: str) -> Optional[List[str]]: 5 | try: 6 | if list_str is None: 7 | return [] 8 | if list_str.strip() == "": 9 | return [] 10 | list_str = list_str.replace("\n*", "\n-").replace("\n%", "\n-") 11 | items = list_str.split("\n-") 12 | items = [line.strip().strip("- \n\t").strip("* \n\t").strip("% \n\t") for line in items] 13 | items = [line for line in items if line != ""] 14 | if len(items) == 0: 15 | return [] 16 | return items 17 | except Exception as e: 18 | return [] 19 | 20 | 21 | def select_testing_framework_from_str(data_str: str) -> Literal["pytest", "unittest"]: 22 | if "unittest" in data_str.lower(): 23 | return "unittest" 24 | else: 25 | return "pytest" -------------------------------------------------------------------------------- /examples/bulleted_list/parse_bulleted_list_modified.py: -------------------------------------------------------------------------------- 1 | from typing import List, Literal, Optional 2 | 3 | 4 | def parse_bullet_list(list_str: str) -> Optional[List[str]]: 5 | try: 6 | if list_str is None: 7 | return [] 8 | if list_str.strip() == "": 9 | return [] 10 | list_str = list_str.replace("\n*", "\n-").replace("\n%", "\n-") 11 | items = list_str.split("\n-") 12 | items = [line.strip().strip("- \n\t").strip("* \n\t").strip("% \n\t") for line in items] 13 | items = [line for line in items if line != ""] 14 | if len(items) == 0: 15 | return [] 16 | return items 17 | except Exception as e: 18 | return [] 19 | 20 | 21 | def select_testing_framework_from_str(data_str: str) -> Literal["pytest", "unittest"]: 22 | if "unittest" in data_str.lower(): 23 | return "unittest" 24 | else: 25 | return "pytest" -------------------------------------------------------------------------------- /examples/bulleted_list/test_parse_bulleted_list.py: -------------------------------------------------------------------------------- 1 | from examples.bulleted_list.parse_bulleted_list import parse_bullet_list 2 | 3 | 4 | class TestParseBulletedList: 5 | def test_parse_multiline_items(self): 6 | """ 7 | Testes the following features: 8 | - For each item, prefix or suffix of whitespaces and / or '-' are ignored. 9 | - Items can be multiline (delimited by '\n-') 10 | """ 11 | data = """ 12 | 13 | - first 14 | still first 15 | --second 16 | 17 | -- -- - third 18 | 19 | It is still third ------ 20 | 21 | """ 22 | expected_first = """first 23 | still first""" 24 | expected_second = "second" 25 | expected_third = """third 26 | 27 | It is still third""" 28 | expected = [ 29 | expected_first, 30 | expected_second, 31 | expected_third, 32 | ] 33 | assert parse_bullet_list(data) == expected 34 | -------------------------------------------------------------------------------- /examples/client_age_generation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/client_age_generation/__init__.py -------------------------------------------------------------------------------- /examples/client_age_generation/client_age_generation.py: -------------------------------------------------------------------------------- 1 | def get_client_age_generation_py(client): 2 | age = client.get('age') 3 | if age is None or age < 0: 4 | return {'set': False} 5 | 6 | if age <= 18: 7 | generation = 'Gen.Z' 8 | elif age < 34: 9 | generation = 'Gen.Y' 10 | else: 11 | generation = 'Gen.X' 12 | 13 | return {'gen': generation, 'set': True} 14 | 15 | def test_valid_client_age_under_18(): 16 | client = {'age': 8} 17 | expected_res = {'gen': 'Gen.Z', 'set': True} 18 | assert get_client_age_generation_py(client) == expected_res 19 | -------------------------------------------------------------------------------- /examples/client_age_generation/test_client_age_generation.py: -------------------------------------------------------------------------------- 1 | # Generated by CodiumAI 2 | from examples.client_age_generation.client_age_generation import get_client_age_generation_py 3 | 4 | 5 | import pytest 6 | 7 | class TestGetClientAgeGenerationPy: 8 | 9 | # Returns {'gen': 'Gen.Z', 'set': True} when client age is 18 or less 10 | def test_client_age_under_18(self): 11 | client = {'age': 8} 12 | expected_res = {'gen': 'Gen.Z', 'set': True} 13 | assert get_client_age_generation_py(client) == expected_res 14 | 15 | # Returns {'gen': 'Gen.Y', 'set': True} when client age is between 18 and 34 16 | def test_client_age_between_18_and_34(self): 17 | client = {'age': 25} 18 | expected_res = {'gen': 'Gen.Y', 'set': True} 19 | assert get_client_age_generation_py(client) == expected_res 20 | 21 | # Returns {'gen': 'Gen.X', 'set': True} when client age is greater than 34 22 | def test_client_age_greater_than_34(self): 23 | client = {'age': 40} 24 | expected_res = {'gen': 'Gen.X', 'set': True} 25 | assert get_client_age_generation_py(client) == expected_res 26 | 27 | # Returns {'set': False} when client age is None 28 | def test_client_age_none(self): 29 | client = {'age': None} 30 | expected_res = {'set': False} 31 | assert get_client_age_generation_py(client) == expected_res 32 | 33 | # Returns {'set': False} when client age is negative 34 | def test_client_age_negative(self): 35 | client = {'age': -10} 36 | expected_res = {'set': False} 37 | assert get_client_age_generation_py(client) == expected_res 38 | 39 | # Returns {'gen': 'Gen.Z', 'set': True} when client age is 0 40 | def test_client_age_zero(self): 41 | client = {'age': 0} 42 | expected_res = {'gen': 'Gen.Z', 'set': True} 43 | assert get_client_age_generation_py(client) == expected_res 44 | -------------------------------------------------------------------------------- /examples/example.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
    5 |
  • text
  • 6 |
7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /examples/library/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/library/__init__.py -------------------------------------------------------------------------------- /examples/library/library.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | from typing import List, Optional 5 | 6 | 7 | class Library: 8 | def __init__(self) -> None: 9 | self._available_books: List[Book] = [] 10 | self._borrowed_books: List[Book] = [] 11 | 12 | def add_new_book_to_library(self, book: Book) -> None: 13 | self._available_books.append(book) 14 | 15 | def remove_book(self, book: Book) -> None: 16 | if book in self._available_books: 17 | self._available_books.remove(book) 18 | if book in self._borrowed_books: 19 | self._borrowed_books.remove(book) 20 | 21 | def borrow_book(self, book: Book) -> None: 22 | if book not in self._available_books: 23 | raise ValueError(f"Book {book} is not available for borrowing") 24 | self._available_books.remove(book) 25 | self._borrowed_books.append(book) 26 | 27 | def return_borrowed_book(self, book: Book) -> None: 28 | if book not in self._borrowed_books: 29 | if not book in self._available_books: 30 | self._available_books.append(book) 31 | raise ValueError(f"Book {book} is not in borrowed books list") 32 | self._borrowed_books.remove(book) 33 | self._available_books.append(book) 34 | 35 | def find_available_book_by_title(self, title: int) -> Optional[Book]: 36 | for book in self._available_books: 37 | if book.title == title: 38 | return book 39 | return None 40 | 41 | def find_available_book_by_author(self, author: int) -> Optional[Book]: 42 | for book in self._available_books: 43 | if book.author == author: 44 | return book 45 | return None 46 | 47 | 48 | @dataclass(frozen=True) 49 | class Book: 50 | title: str 51 | author: str 52 | -------------------------------------------------------------------------------- /examples/library_2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/library_2/__init__.py -------------------------------------------------------------------------------- /examples/library_2/book_2.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | 6 | @dataclass(frozen=True) 7 | class Book2: 8 | title: str 9 | author: str 10 | -------------------------------------------------------------------------------- /examples/library_2/library_2.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import List, Optional 4 | 5 | from examples.library_2.book_2 import Book2 6 | 7 | 8 | class Library2: 9 | def __init__(self) -> None: 10 | self._available_books: List[Book2] = [] 11 | self._borrowed_books: List[Book2] = [] 12 | 13 | def add_new_book_to_library(self, book: Book2) -> None: 14 | self._available_books.append(book) 15 | 16 | def remove_book(self, book: Book2) -> None: 17 | if book in self._available_books: 18 | self._available_books.remove(book) 19 | if book in self._borrowed_books: 20 | self._borrowed_books.remove(book) 21 | 22 | def borrow_book(self, book: Book2) -> None: 23 | if book not in self._available_books: 24 | raise ValueError(f"Book {book} is not available for borrowing") 25 | self._available_books.remove(book) 26 | self._borrowed_books.append(book) 27 | 28 | def return_borrowed_book(self, book: Book2) -> None: 29 | if book not in self._borrowed_books: 30 | if not book in self._available_books: 31 | self._available_books.append(book) 32 | raise ValueError(f"Book {book} is not in borrowed books list") 33 | self._borrowed_books.remove(book) 34 | self._available_books.append(book) 35 | 36 | def find_available_book_by_title(self, title: int) -> Optional[Book2]: 37 | for book in self._available_books: 38 | if book.title == title: 39 | return book 40 | return None 41 | 42 | def find_available_book_by_author(self, author: int) -> Optional[Book2]: 43 | for book in self._available_books: 44 | if book.author == author: 45 | return book 46 | return None 47 | -------------------------------------------------------------------------------- /examples/library_2/random_data_gen.py: -------------------------------------------------------------------------------- 1 | 2 | from examples.library_2.book_2 import Book2 3 | import random 4 | 5 | 6 | def random_book() -> Book2: 7 | # https://datavizblog.com/2018/12/21/dataviz-humor-oreilly-programming-book-parody-covers/ 8 | BOOK_TITLES = [ 9 | "Blaming the user", 10 | "Vague understanding of computer science", 11 | "Writing code that nobody else can read", 12 | "Pointless meetings", 13 | "Coding drunk", 14 | "Buzzword-first design", 15 | ] 16 | 17 | AUTHORS = [ 18 | "Bright-eyed junior", 19 | "Disillusioned senior", 20 | "A tired developer", 21 | "Dev with unrealistic deadlines", 22 | ] 23 | return Book2( 24 | title=random.choice(BOOK_TITLES), 25 | author=random.choice(AUTHORS), 26 | ) 27 | -------------------------------------------------------------------------------- /examples/library_2/test_library_2.py: -------------------------------------------------------------------------------- 1 | 2 | from examples.library_2.book_2 import Book2 3 | from examples.library_2.library_2 import Library2 4 | from examples.library_2.random_data_gen import random_book 5 | 6 | class TestLibrary2: 7 | def setup_method(self): 8 | self.library = Library2() 9 | 10 | def test_add_new_book_to_library(self): 11 | book: Book2 = random_book() 12 | self.library.add_new_book_to_library(book) 13 | assert book in self.library._available_books 14 | -------------------------------------------------------------------------------- /examples/library_3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/library_3/__init__.py -------------------------------------------------------------------------------- /examples/library_3/active_borrow.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | 4 | @dataclass() 5 | class ActiveBorrow: 6 | uid: str 7 | book_id: str 8 | user_id: str 9 | -------------------------------------------------------------------------------- /examples/library_3/admin.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.user import User 2 | 3 | 4 | class Admin(User): 5 | def __init__(self, uid, username, password): 6 | super().__init__(uid, username, password) 7 | -------------------------------------------------------------------------------- /examples/library_3/admin_management.py: -------------------------------------------------------------------------------- 1 | class AdminManagement: 2 | def __init__(self, acting_user, user_db): 3 | self._user_db = user_db 4 | self._acting_user = acting_user 5 | 6 | def new_user(self, role, username, password): 7 | return self._user_db.new_user(role, username, password) 8 | 9 | def get_user_by_username(self, username): 10 | return self._user_db.get_user_by_username(username) 11 | 12 | def delete_user(self, uid): 13 | self._user_db.remove_user(uid) 14 | 15 | def update_user(self, user): 16 | # Update user info 17 | pass 18 | 19 | -------------------------------------------------------------------------------- /examples/library_3/admin_management_factory.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.admin_management import AdminManagement 2 | 3 | 4 | class AdminManagementFactory: 5 | def __init__(self, user_db): 6 | self._user_db = user_db 7 | 8 | def get_admin_management(self, user): 9 | return AdminManagement(user, self._user_db) 10 | -------------------------------------------------------------------------------- /examples/library_3/audit_log.py: -------------------------------------------------------------------------------- 1 | class AuditLog: 2 | def __init__(self, library): 3 | self.library = library 4 | self.audit_log_db = library.audit_log 5 | 6 | def add_audit_log(self, action): 7 | # Add an audit log 8 | pass 9 | 10 | def find_audit_logs(self, user, action): 11 | # Find audit logs by user and action 12 | pass 13 | -------------------------------------------------------------------------------- /examples/library_3/audit_log_db.py: -------------------------------------------------------------------------------- 1 | class AuditLogDB: 2 | def __init__(self): 3 | self.audit_logs = [] 4 | 5 | def add_audit_log(self, action, user): 6 | self.audit_logs.append((action, user)) 7 | -------------------------------------------------------------------------------- /examples/library_3/book_borrowing_db.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.active_borrow import ActiveBorrow 2 | 3 | 4 | class BookBorrowingDB: 5 | def __init__(self): 6 | self._active_borrows = {} 7 | self._next_uid = 1 8 | 9 | def _get_next_id(self): 10 | uid = self._next_uid 11 | self._next_uid += 1 12 | return uid 13 | 14 | def borrow(self, book_id, user_id): 15 | active_borrow = ActiveBorrow( 16 | self._get_next_id(), 17 | book_id, 18 | user_id, 19 | ) 20 | self._active_borrows[active_borrow.uid] = active_borrow 21 | return active_borrow 22 | 23 | def return_book(self, book_id, user): 24 | for borrow in self._active_borrows.values(): 25 | if borrow.book_id == book_id and borrow.user_id == user.uid: 26 | self._active_borrows.pop(borrow.uid) 27 | else: 28 | raise ValueError(f"Book with UID {book_id} is not borrowed by user {user.uid}") 29 | 30 | def get_active_borrows(self, book_id): 31 | return [borrow for borrow in self._active_borrows.values() if borrow.book_id == book_id] 32 | -------------------------------------------------------------------------------- /examples/library_3/book_info.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | @dataclass() 4 | class BookInfo: 5 | uid: str 6 | title: str 7 | author: str 8 | -------------------------------------------------------------------------------- /examples/library_3/book_inventory_listing.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from examples.library_3.book_info import BookInfo 4 | 5 | @dataclass() 6 | class BookInventoryListing: 7 | """ 8 | The listing inside the inventory, that doesn't change as we borrow books. 9 | """ 10 | uid: str 11 | book_info: BookInfo 12 | existing_copies_count: int 13 | -------------------------------------------------------------------------------- /examples/library_3/book_listing.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from examples.library_3.book_info import BookInfo 4 | 5 | @dataclass() 6 | class BookListing: 7 | uid: str 8 | book_info: BookInfo 9 | existing_copies_count: int 10 | available_copies_count: int 11 | -------------------------------------------------------------------------------- /examples/library_3/copy_of_test_library.py: -------------------------------------------------------------------------------- 1 | # from examples.library_3.admin import Admin 2 | # from examples.library_3.member import Member 3 | # from examples.library_3.librarian import Librarian 4 | # from examples.library_3.permissions import UserRole 5 | # from examples.library_3.library_factory import make_new_library 6 | 7 | 8 | # class TestLibrary3: 9 | # def setup_method(self): 10 | # self.library, self.root_user = make_new_library("root", "super-secret-root-pass") 11 | 12 | # def test_create_new_user(self): 13 | # admin_mgmt = self.library.get_admin_management(self.root_user) 14 | # librarian_created = admin_mgmt.new_user(UserRole.LIBRARIAN, "giles", "watcher-on-the-wall") 15 | 16 | # librarian_retrieved = admin_mgmt.get_user_by_username("giles") 17 | 18 | # assert librarian_retrieved.uid == librarian_created.uid 19 | 20 | 21 | 22 | 23 | 24 | # # def test_borrow_book(library): 25 | # # user_book_management = library.get_user_book_management(Member("John", "pass1234")) 26 | # # book = BookListing("Book Title", "Author Name", "2022-01-01", 2) 27 | # # user_book_management.borrow_book(book, Member("John", "pass1234")) 28 | # # assert book.available_count == 1 29 | 30 | # # root_admin = Admin("root", "rootpass") 31 | 32 | # # library = Library(root_admin) 33 | 34 | # # global_book_db = GlobalBookDB() 35 | # # library_book_db = LibraryBookDB() 36 | # # book_borrowing_db = BookBorrowingDB() 37 | # # user_book_management = UserBookManagement(library) 38 | # # librarian_book_management = LibrarianBookManagement(library) 39 | # # user_management = UserManagement(library) 40 | # # admin_management = AdminManagement(library) 41 | # # user_db = UserDB() 42 | # # audit_log_db = AuditLogDB() 43 | # # audit_log = AuditLog(library) 44 | 45 | # # library.set_librarian_book_management(librarian_book_management) 46 | # # library.set_user_book_management(user_book_management) 47 | # # library.set_user_management(user_management) 48 | # # library.set_admin_management(admin_management) 49 | # # library.set_audit_log(audit_log) 50 | 51 | # # test_borrow_book(library) -------------------------------------------------------------------------------- /examples/library_3/in_memory_library_book_db.py: -------------------------------------------------------------------------------- 1 | class InMemoryLibraryBookDB: 2 | """ 3 | Books that are available in the library. 4 | Does not track borrowing actions - only the full inventory. 5 | """ 6 | def __init__(self): 7 | self._books = {} 8 | 9 | def add_book(self, book_listing): 10 | if book_listing.uid in self._books: 11 | raise ValueError(f"Book with UID {book_listing.uid} already exists") 12 | self._books[book_listing.uid] = book_listing 13 | 14 | def find_books(self, author=None, title=None): 15 | with_author = self.filter_books_by_author(author, self._books.values()) 16 | with_author_and_title = self.filter_books_by_title(title, with_author) 17 | 18 | return with_author_and_title 19 | 20 | def filter_books_by_author(self, author, orig_list): 21 | if author is None: 22 | return orig_list 23 | else: 24 | return [book for book in orig_list if book.book_info.author == author] 25 | 26 | def filter_books_by_title(self, title, orig_list): 27 | if title is None: 28 | return orig_list 29 | else: 30 | return [book for book in orig_list if book.book_info.title == title] 31 | 32 | def find_book_by_id(self, book_id): 33 | return self._books.get(book_id) 34 | 35 | def update_copies_count(self, book_id, copies_count): 36 | if copies_count < 0: 37 | raise ValueError("Copies count cannot be negative") 38 | if book_id not in self._books: 39 | raise ValueError(f"Book with UID {book_id} does not exist") 40 | if copies_count == 0: 41 | del self._books[book_id] 42 | else: 43 | self._books[book_id].existing_copies_count = copies_count 44 | 45 | 46 | def remove_book(self, book_id): 47 | self.update_copies_count(book_id, 0) 48 | -------------------------------------------------------------------------------- /examples/library_3/in_memory_user_db.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.admin import Admin 2 | from examples.library_3.member import Member 3 | from examples.library_3.librarian import Librarian 4 | from examples.library_3.permissions import UserRole 5 | 6 | class InMemoryUserDB: 7 | def __init__(self, root_user): 8 | self._user_id_to_user = { 9 | root_user.uid: root_user, 10 | } 11 | self._next_uid = root_user.uid + 1 12 | 13 | def new_user(self, role, username, password): 14 | user = self._mk_new_user(role, username, password) 15 | self._user_id_to_user[user.uid] = user 16 | return user 17 | 18 | def _mk_new_user(self, role, username, password): 19 | for user in self._user_id_to_user.values(): 20 | if user.username == username: 21 | raise ValueError(f"Username {username} is already exists") 22 | if role == UserRole.ADMIN: 23 | return Admin(self._get_next_user_id(), username, password) 24 | elif role == UserRole.MEMBER: 25 | return Member(self._get_next_user_id(), username, password) 26 | elif role == UserRole.LIBRARIAN: 27 | return Librarian(self._get_next_user_id(), username, password) 28 | else: 29 | raise ValueError(f"Unknown role: {role}") 30 | 31 | def _get_next_user_id(self): 32 | uid = self._next_uid 33 | self._next_uid += 1 34 | return uid 35 | 36 | def remove_user(self, uid): 37 | self._user_id_to_user.pop(uid) 38 | 39 | def get_user(self, uid): 40 | return self._user_id_to_user.get(uid) 41 | 42 | def get_user_by_username(self, username): 43 | for user in self._user_id_to_user.values(): 44 | if user.username == username: 45 | return user 46 | return None 47 | 48 | def get_user_by_username_and_password(self, username, password): 49 | for user in self._user_id_to_user.values(): 50 | if user.username == username and user.password == password: 51 | return user 52 | return None 53 | 54 | 55 | # def update_user(self, user): 56 | # # Update user info 57 | # pass 58 | -------------------------------------------------------------------------------- /examples/library_3/librarian.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.user import User 2 | 3 | 4 | class Librarian(User): 5 | def __init__(self, uid, username, password): 6 | super().__init__(uid, username, password) 7 | -------------------------------------------------------------------------------- /examples/library_3/librarian_book_management.py: -------------------------------------------------------------------------------- 1 | class LibrarianBookManagement: 2 | def __init__(self, 3 | acting_user, 4 | library_book_db, 5 | book_borrowing_db, 6 | ): 7 | self._acting_user = acting_user 8 | self._library_book_db = library_book_db 9 | self._book_borrowing_db = book_borrowing_db 10 | 11 | def add_book(self, book_listing): 12 | self._library_book_db.add_book(book_listing) 13 | 14 | 15 | def find_books(self, author=None, title=None): 16 | return self._library_book_db.find_books(author, title) 17 | 18 | def borrow_book(self, book, user): 19 | # Borrow a book on behalf of a user 20 | pass 21 | 22 | def return_book(self, book, user): 23 | # Return a book on behalf of a user 24 | pass 25 | -------------------------------------------------------------------------------- /examples/library_3/librarian_book_management_factory.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.librarian_book_management import LibrarianBookManagement 2 | 3 | 4 | class LibrarianBookManagementFactory: 5 | def __init__( 6 | self, 7 | library_book_db, 8 | book_borrowing_db, 9 | ): 10 | self._library_book_db = library_book_db 11 | self._book_borrowing_db = book_borrowing_db 12 | 13 | def get_librarian_book_management(self, acting_user): 14 | return LibrarianBookManagement( 15 | acting_user=acting_user, 16 | library_book_db=self._library_book_db, 17 | book_borrowing_db=self._book_borrowing_db, 18 | ) 19 | -------------------------------------------------------------------------------- /examples/library_3/library_3.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.permissions import ( 2 | is_admin, 3 | is_librarian, 4 | is_member, 5 | ) 6 | 7 | 8 | class Library3: 9 | def __init__( 10 | self, 11 | librarian_book_management_factory, 12 | member_book_management_factory, 13 | # user_management, 14 | admin_management_factory, 15 | # audit_log, 16 | ): 17 | self._librarian_book_management_factory = librarian_book_management_factory 18 | self._member_book_management_factory = member_book_management_factory 19 | # self.user_book_management = None 20 | # self.user_management = None 21 | self._admin_management_factory = admin_management_factory 22 | # self.audit_log = None 23 | 24 | def get_librarian_book_management(self, acting_user): 25 | if is_librarian(acting_user): 26 | return self._librarian_book_management_factory.get_librarian_book_management(acting_user) 27 | else: 28 | raise Exception("User is not authorized to access LibrarianBookManagement") 29 | 30 | def get_member_book_management(self, acting_user): 31 | if is_member(acting_user): 32 | return self._member_book_management_factory.get_member_book_management(acting_user) 33 | else: 34 | raise Exception("User is not authorized to access LibrarianBookManagement") 35 | 36 | # def get_user_book_management(self, user): 37 | # if user.is_member(): 38 | # return self.user_book_management 39 | # else: 40 | # raise Exception("User is not authorized to access UserBookManagement") 41 | 42 | # def get_user_management(self, user): 43 | # if user.is_admin() or user.is_librarian(): 44 | # return self.user_management 45 | # else: 46 | # raise Exception("User is not authorized to access UserManagement") 47 | 48 | def get_admin_management(self, user): 49 | if is_admin(user): 50 | return self._admin_management_factory.get_admin_management(user) 51 | else: 52 | raise Exception("User is not authorized to access AdminManagement") 53 | -------------------------------------------------------------------------------- /examples/library_3/library_factory.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.admin import Admin 2 | from examples.library_3.librarian_book_management_factory import LibrarianBookManagementFactory 3 | from examples.library_3.library_3 import Library3 4 | from examples.library_3.in_memory_user_db import InMemoryUserDB 5 | from examples.library_3.admin_management_factory import AdminManagementFactory 6 | from examples.library_3.librarian_book_management import LibrarianBookManagement 7 | from examples.library_3.member_book_management import MemberBookManagement 8 | from examples.library_3.in_memory_library_book_db import InMemoryLibraryBookDB 9 | from examples.library_3.book_borrowing_db import BookBorrowingDB 10 | from examples.library_3.member_book_management_factory import MemberBookManagementFactory 11 | 12 | 13 | def make_new_library(root_username, root_password): 14 | root_user = Admin(1, root_username, root_password) 15 | 16 | user_db = InMemoryUserDB(root_user) 17 | admin_management_factory = AdminManagementFactory(user_db) 18 | 19 | book_db = InMemoryLibraryBookDB() 20 | borrowing_db = BookBorrowingDB() 21 | 22 | librarian_book_management_factory = LibrarianBookManagementFactory( 23 | library_book_db=book_db, 24 | book_borrowing_db=borrowing_db, 25 | ) 26 | 27 | member_book_management_factory = MemberBookManagementFactory( 28 | library_book_db=book_db, 29 | book_borrowing_db=borrowing_db, 30 | ) 31 | 32 | library = Library3( 33 | librarian_book_management_factory=librarian_book_management_factory, 34 | member_book_management_factory=member_book_management_factory, 35 | admin_management_factory=admin_management_factory, 36 | ) 37 | return library, root_user 38 | -------------------------------------------------------------------------------- /examples/library_3/member.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.user import User 2 | 3 | 4 | class Member(User): 5 | def __init__(self, uid, username, password): 6 | super().__init__(uid, username, password) 7 | -------------------------------------------------------------------------------- /examples/library_3/member_book_management.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.book_listing import BookListing 2 | 3 | 4 | class MemberBookManagement: 5 | def __init__( 6 | self, 7 | acting_user, 8 | library_book_db, 9 | book_borrowing_db, 10 | ): 11 | self._acting_user = acting_user 12 | self._library_book_db = library_book_db 13 | self._book_borrowing_db = book_borrowing_db 14 | 15 | def find_books(self, author=None, title=None): 16 | inventory_books = self._library_book_db.find_books(author, title) 17 | 18 | def listing_for_inventory_listing(self, book_inventory_listing): 19 | book_id = book_inventory_listing.uid 20 | active_borrows = self._book_borrowing_db.get_active_borrows(book_id) 21 | available_copies_count = book_inventory_listing.existing_copies_count - len(active_borrows) 22 | 23 | return BookListing( 24 | uid=book_inventory_listing.uid, 25 | book_info=book_inventory_listing.book_info, 26 | existing_copies_count=book_inventory_listing.existing_copies_count, 27 | available_copies_count=available_copies_count, 28 | ) 29 | 30 | def borrow_book(self, book_id): 31 | book_listing = self._library_book_db.find_book_by_id(book_id) 32 | active_borrows = self._book_borrowing_db.get_active_borrows(book_id) 33 | 34 | if book_listing.existing_copies_count - len(active_borrows) <= 0: 35 | raise ValueError("There are no copies of this book available for borrowing") 36 | return self._book_borrowing_db.borrow(book_listing.uid, self._acting_user.uid) 37 | 38 | def return_book(self, book, user): 39 | # Return a book 40 | pass 41 | -------------------------------------------------------------------------------- /examples/library_3/member_book_management_factory.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.member_book_management import MemberBookManagement 2 | 3 | 4 | class MemberBookManagementFactory: 5 | def __init__( 6 | self, 7 | library_book_db, 8 | book_borrowing_db, 9 | ): 10 | self._library_book_db = library_book_db 11 | self._book_borrowing_db = book_borrowing_db 12 | 13 | def get_member_book_management(self, acting_user): 14 | return MemberBookManagement( 15 | acting_user=acting_user, 16 | library_book_db=self._library_book_db, 17 | book_borrowing_db=self._book_borrowing_db, 18 | ) 19 | -------------------------------------------------------------------------------- /examples/library_3/permissions.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.admin import Admin 2 | from examples.library_3.member import Member 3 | from examples.library_3.librarian import Librarian 4 | 5 | 6 | def is_admin(user): 7 | return isinstance(user, Admin) 8 | 9 | def is_member(user): 10 | return isinstance(user, Member) 11 | 12 | def is_librarian(user): 13 | return isinstance(user, Librarian) 14 | 15 | class UserRole: 16 | MEMBER = "member" 17 | LIBRARIAN = "librarian" 18 | ADMIN = "admin" 19 | -------------------------------------------------------------------------------- /examples/library_3/test_library.py: -------------------------------------------------------------------------------- 1 | from examples.library_3.admin import Admin 2 | from examples.library_3.book_info import BookInfo 3 | from examples.library_3.book_inventory_listing import BookInventoryListing 4 | from examples.library_3.book_listing import BookListing 5 | from examples.library_3.member import Member 6 | from examples.library_3.librarian import Librarian 7 | from examples.library_3.permissions import UserRole 8 | from examples.library_3.library_factory import make_new_library 9 | 10 | 11 | class TestLibrary3: 12 | def setup_method(self): 13 | self.library, self.root_user = make_new_library("root", "super-secret-root-pass") 14 | 15 | def test_admin_can_create_new_librarian_user(self): 16 | admin_mgmt = self.library.get_admin_management(self.root_user) 17 | librarian_created = admin_mgmt.new_user(UserRole.LIBRARIAN, "Giles", "watcher-on-the-wall") 18 | 19 | librarian_retrieved = admin_mgmt.get_user_by_username("Giles") 20 | 21 | assert librarian_retrieved.uid == librarian_created.uid 22 | 23 | def test_admin_can_delete_user(self): 24 | admin_mgmt = self.library.get_admin_management(self.root_user) 25 | librarian_created = admin_mgmt.new_user(UserRole.LIBRARIAN, "Giles", "watcher-on-the-wall") 26 | 27 | # Verify the user exists 28 | librarian_retrieved = admin_mgmt.get_user_by_username("Giles") 29 | assert librarian_retrieved.uid == librarian_created.uid 30 | 31 | admin_mgmt.delete_user(librarian_created.uid) 32 | librarian_retrieved_after_delete = admin_mgmt.get_user_by_username("Giles") 33 | assert librarian_retrieved_after_delete is None 34 | 35 | def test_librarian_can_add_books(self): 36 | admin_mgmt = self.library.get_admin_management(self.root_user) 37 | librarian = admin_mgmt.new_user(UserRole.LIBRARIAN, "Giles", "watcher-on-the-wall") 38 | 39 | librarian_book_mgmt = self.library.get_librarian_book_management(librarian) 40 | 41 | book_info = BookInfo( 42 | uid="book-info-uid-1", 43 | author="Dracula", 44 | title="Yummy Humans", 45 | ) 46 | book_listing = BookInventoryListing( 47 | uid="book-listing-uid-1", 48 | book_info=book_info, 49 | existing_copies_count=3, 50 | ) 51 | librarian_book_mgmt.add_book(book_listing) 52 | 53 | book_listing_retrieved = librarian_book_mgmt.find_books(author="Dracula") 54 | assert book_listing_retrieved == [book_listing] 55 | 56 | 57 | def test_user_can_borrow_book(self): 58 | admin_mgmt = self.library.get_admin_management(self.root_user) 59 | librarian = admin_mgmt.new_user(UserRole.LIBRARIAN, "Giles", "watcher-on-the-wall") 60 | member = admin_mgmt.new_user(UserRole.MEMBER, "Willow", "its-magic") 61 | 62 | librarian_book_mgmt = self.library.get_librarian_book_management(librarian) 63 | 64 | book_info = BookInfo( 65 | uid="book-info-uid-1", 66 | author="Dracula", 67 | title="Yummy Humans", 68 | ) 69 | book_listing = BookInventoryListing( 70 | uid="book-listing-uid-1", 71 | book_info=book_info, 72 | existing_copies_count=3, 73 | ) 74 | librarian_book_mgmt.add_book(book_listing) 75 | 76 | member_book_mgmt = self.library.get_member_book_management(member) 77 | 78 | borrow = member_book_mgmt.borrow_book(book_listing.uid) 79 | 80 | assert borrow is not None 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /examples/library_3/user.py: -------------------------------------------------------------------------------- 1 | class User: 2 | def __init__(self, uid, username, password): 3 | self.uid = uid 4 | self.username = username 5 | self.password = password 6 | -------------------------------------------------------------------------------- /examples/library_3/user_book_management.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/library_3/user_book_management.py -------------------------------------------------------------------------------- /examples/library_3/user_management.py: -------------------------------------------------------------------------------- 1 | class UserManagement: 2 | def __init__(self, library): 3 | self.library = library 4 | 5 | def create_user(self, username, password, role): 6 | # Create a new user 7 | pass 8 | 9 | def delete_user(self, user): 10 | # Delete a user 11 | pass 12 | 13 | def update_user(self, user): 14 | # Update user info 15 | pass 16 | 17 | -------------------------------------------------------------------------------- /examples/quick_sort/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/quick_sort/__init__.py -------------------------------------------------------------------------------- /examples/quick_sort/quick_sort.py: -------------------------------------------------------------------------------- 1 | def qsort(lst): 2 | if len(lst) < 2: 3 | return lst 4 | 5 | first_item = lst[0] 6 | rest_of_list = lst[1:] 7 | 8 | smaller_than_first = [k for k in rest_of_list if k <= first_item] 9 | larger_than_first = [k for k in rest_of_list if k > first_item] 10 | 11 | return qsort(smaller_than_first) + [first_item] + qsort(larger_than_first) 12 | -------------------------------------------------------------------------------- /examples/quick_sort/test_quick_sort.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from hypothesis import given 3 | import hypothesis.strategies as some 4 | 5 | from examples.quick_sort.quick_sort import qsort 6 | 7 | class TestQuickSort: 8 | @pytest.mark.parametrize( 9 | "l,expected", 10 | [ 11 | ([], []), 12 | ([1], [1]), 13 | ] 14 | ) 15 | def test_sort_simple_lists(self, l, expected): 16 | expected_copy = expected[:] 17 | assert qsort(l) == expected_copy 18 | 19 | class TestQuickSortPBT: 20 | @given(some.lists(some.integers())) 21 | def test_sort_is_idempotent(self, lst): 22 | assert qsort(qsort(lst)) == qsort(lst) 23 | -------------------------------------------------------------------------------- /examples/user.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE User ( 2 | id INT NOT NULL AUTO_INCREMENT, 3 | username VARCHAR(255) NOT NULL, 4 | email VARCHAR(255) NOT NULL, 5 | password VARCHAR(255) NOT NULL, 6 | created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | last_login TIMESTAMP, 8 | PRIMARY KEY (id), 9 | UNIQUE KEY (username), 10 | UNIQUE KEY (email) 11 | ); 12 | -------------------------------------------------------------------------------- /examples/yaml_strip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/examples/yaml_strip/__init__.py -------------------------------------------------------------------------------- /examples/yaml_strip/test_yaml_strip.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from examples.yaml_strip.yaml_strip import yaml_safe_load 3 | 4 | class TestYamlStrip: 5 | @pytest.mark.parametrize( 6 | "yaml_str,expected", 7 | [ 8 | ("""\ 9 | foo: bar""", {"foo": "bar"}), 10 | ] 11 | ) 12 | def test_clean_yaml(self, yaml_str, expected): 13 | assert yaml_safe_load(yaml_str) == expected 14 | -------------------------------------------------------------------------------- /examples/yaml_strip/yaml_strip.py: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import Optional 3 | import yaml 4 | 5 | def yaml_safe_load(s): 6 | try: 7 | return yaml.safe_load(strip_yaml(s)) 8 | except Exception: 9 | return None 10 | 11 | def strip_yaml(yaml_str: Optional[str]) -> Optional[str]: 12 | if yaml_str is None: 13 | return None 14 | return re.sub(r'^```yaml', '', yaml_str).rstrip('`') 15 | -------------------------------------------------------------------------------- /media/docs/Closedalphabanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Closedalphabanner.png -------------------------------------------------------------------------------- /media/docs/Generatetests013_org_long.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Generatetests013_org_long.gif -------------------------------------------------------------------------------- /media/docs/GeneratetestsV2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/GeneratetestsV2.gif -------------------------------------------------------------------------------- /media/docs/Joincommunity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Joincommunity.png -------------------------------------------------------------------------------- /media/docs/Step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step1.png -------------------------------------------------------------------------------- /media/docs/Step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step2.png -------------------------------------------------------------------------------- /media/docs/Step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step3.png -------------------------------------------------------------------------------- /media/docs/Step4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step4.png -------------------------------------------------------------------------------- /media/docs/Step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step5.png -------------------------------------------------------------------------------- /media/docs/Step6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step6.png -------------------------------------------------------------------------------- /media/docs/Step7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step7.png -------------------------------------------------------------------------------- /media/docs/Step8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Step8.png -------------------------------------------------------------------------------- /media/docs/TestGeneration.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/TestGeneration.gif -------------------------------------------------------------------------------- /media/docs/Tip1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/Tip1.png -------------------------------------------------------------------------------- /media/docs/auth1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/auth1.png -------------------------------------------------------------------------------- /media/docs/auth2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/auth2.png -------------------------------------------------------------------------------- /media/docs/auth3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/auth3.png -------------------------------------------------------------------------------- /media/docs/auth4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/auth4.png -------------------------------------------------------------------------------- /media/docs/generateButtons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/generateButtons.png -------------------------------------------------------------------------------- /media/docs/installed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/installed.png -------------------------------------------------------------------------------- /media/docs/signin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/signin.png -------------------------------------------------------------------------------- /media/docs/uninstallS1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codium-ai/codium-code-examples/1e05b7cc4244cb6054fc7593cb3ddcd5c4bd168d/media/docs/uninstallS1.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | text-unidecode == 1.3 3 | Unidecode == 1.1.1 4 | --------------------------------------------------------------------------------