Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: 2.1

jobs:
test:
docker:
- image: cimg/python:3.12
steps:
- checkout
- run:
name: Install uv
command: |
curl -sSL https://install.uv.tools | bash
- run:
name: Install dependencies
command: uv init # Installs dependencies from pyproject.toml
- run:
name: Run pytest tests
command: pytest tests
- run:
name: Run ruff for linting
command: ruff check .
- run:
name: Run mypy for type checking
command: mypy .

workflows:
version: 2
test_and_static_analysis:
jobs:
- test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ dmypy.json
# Cython debug symbols
cython_debug/

# Mac metadata file
.DS_Store

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
117 changes: 116 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,116 @@
# mAIgic-nyu
# mAIgic

## Project Description
**mAIgic** is an AI-powered assistant designed to enhance productivity and organization by tracking messages and important information across multiple platforms. It identifies and reminds users about follow-ups, ensuring timely responses and efficient information management. With intelligent search capabilities, mAIgic enables users to easily locate conversations and details tied to specific individuals or tasks.

The project supports popular platforms such as Slack, Trello, and Gmail, providing seamless follow-up tracking, reminders, and contextual search across these communication channels. This integration leverages AI to automate the reminder process, making it easier to stay on top of essential follow-ups and tasks.

## Features
- Unit testing with `pytest`
- Static code analysis with `ruff` (linter)
- Type checking with `mypy`
- Continuous Integration (CI) pipeline with CircleCI, running both tests and static analysis automatically on every push.

---

## Setup Instructions

### 1. Clone the Repository
```bash
git clone https://github.com/your-username/mAIgic.git
cd mAIgic
```

### 2. Install Dependencies
```bash
pip install -r requirements.txt
```

Alternatively, if using the `uv` package manager:
```bash
uv sync
```

The above command will create a virtual environment `.venv` and install all the dependencies from the `uv.lock` file. Activate the environment by executing
```bash
source .venv/bin/activate
```

---

## Running Tests

### 1. Pytest
You can run unit tests using `pytest` by running the following command:
```bash
pytest tests
```

**Example Tests in `tests/test_samples.py`:**
- Basic arithmetic (addition, subtraction, multiplication, division)
- String operations (case-insensitive checks)
- List and dictionary operations
- Exception handling tests (checking for specific exceptions)

### 2. Ruff (Linter)
Use `ruff` to run static analysis (linting) on your code:
```bash
ruff check .
```

### 3. Mypy (Type Checking)
To perform static type checking using `mypy`, run:
```bash
mypy .
```

---

## CircleCI Configuration

The project is integrated with CircleCI for continuous integration. Every push to the repository automatically triggers the following steps:
1. **Install dependencies**: Installs `pytest`, `ruff`, and `mypy`.
2. **Run tests**: Executes all tests in the `tests/` folder using `pytest`.
3. **Run static analysis**: Runs `ruff` for linting and `mypy` for type checking.



### View CircleCI Status:
The latest CircleCI build can be viewed [here](https://app.circleci.com/pipelines/circleci/L7kpZ5X2tZyEgUBhR4SB2j/NxWta8V9bEwRzTNu9Vzc3c/9/workflows/be567b6f-0c9c-41c8-91f7-e4789784b41f).

---

## Troubleshooting

### Common Errors:
1. **Missing Dependencies**: If any dependency-related issues arise, ensure all dependencies are installed by running:
```bash
pip install -r requirements.txt
```
or
```bash
uv init
```


## License
This project is licensed under the MIT License.


### Explanation of the Sections:

1. **Project Description**: Provides an overview of what the project does.
2. **Features**: Highlights the major tools and features used.
3. **Setup Instructions**: Guides users on how to clone the repo, install dependencies, and initialize the project.
4. **Running Tests**: Explains how to run unit tests, static analysis, and type checks.
5. **CircleCI Configuration**: Outlines how CircleCI automates the process of testing and analysis, including the YAML configuration.
6. **Troubleshooting**: Offers solutions for common errors like string comparison and missing dependencies.
7. **License**: A placeholder for your project's license type.

## Teammates
- Siddharth Singh - sms10221@nyu.edu
- Adittya Mittal - am14079@nyu.edu
- Anushka Tawte - at5849@nyu.edu
- Rafael de Leon - rdl404@nyu.edu
- Alex Ying - aty2009@nyu.edu
- Mridul Mittal - mm13171@nyu.edu
3 changes: 3 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[mypy]
python_version = 3.12
ignore_missing_imports = True
17 changes: 17 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[project]
name = "mAIgic"
version = "0.1.0"
description = "An AI-powered assistant designed to enhance productivity and organization by tracking messages and important information across multiple platforms"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pytest",
"ruff",
"mypy",
"slack-bolt>=1.21.2",
"python-dotenv>=1.0.1",
]

[tool.ruff.lint]
select = ["ALL"]
extend-ignore = ["S101", "D211", "D213"]
Binary file added requirements.txt
Binary file not shown.
21 changes: 21 additions & 0 deletions src/hello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
from maigic_nyu.api import SlackApp
from dotenv import load_dotenv


# Example usage
def message_handler(message, say):
say(f"Hey there <@{message['user']}>! I am responding to: {message['text']}")


def main() -> None:
load_dotenv()
app = SlackApp(
message_handler=message_handler,
bot_token=os.environ.get("SLACK_BOT_TOKEN"),
app_token=os.environ["SLACK_APP_TOKEN"]
)
app.run()

if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions src/maigic_nyu/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Make maigic_nyu directory a referenceable package."""
16 changes: 16 additions & 0 deletions src/maigic_nyu/_temp_math.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Placeholder API file to test imports."""

def add(num1:int, num2:int) -> int:
return num1 + num2

def subtract(num1:int, num2:int) -> int:
return num1 - num2

def multiply(num1:int, num2:int) -> int:
return num1 * num2

def divide(num1:int, num2:int) -> float:
return num1 / num2

def modulo(num1:int, num2:int) -> int:
return num1 % num2
9 changes: 9 additions & 0 deletions src/maigic_nyu/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ._temp_math import (
add as add,
divide as divide,
modulo as modulo,
multiply as multiply,
subtract as subtract,
)

from .slackbot.slackbot import SlackApp as SlackApp
3 changes: 3 additions & 0 deletions src/maigic_nyu/slackbot/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Make slack directory a referenceable package."""

# from slackbot import SlackApp as SlackApp
23 changes: 23 additions & 0 deletions src/maigic_nyu/slackbot/slackbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_bolt.error import BoltError

class SlackApp:
def __init__(self, message_handler, bot_token, app_token):
# Attempts to initializes app with bot token and socket mode handler
try:
self.app = App(token=os.environ.get(bot_token))
@self.app.message()
def wrapped_handler(message, say):
self.handler(message, say)

self.handler = message_handler
self.socket = SocketModeHandler(self.app, app_token)
except BoltError as e:
# Generally, this error arises if the "SLACK_BOT_TOKEN" is invalid
print("Error initializing Slack App:", e)

def run(self):
self.socket.start()

1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Make tests directory as a referenceable package."""
22 changes: 22 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from src.maigic_nyu.api import (
add as add,
divide as divide,
modulo as modulo,
multiply as multiply,
subtract as subtract,
)

def test_api_add() -> None:
assert add(7, 2) == 9

def test_api_subtract() -> None:
assert subtract(7, 2) == 5

def test_api_multiply() -> None:
assert multiply(7, 2) == 14

def test_api_divide() -> None:
assert divide(7, 2) == 3.5

def test_api_modulo() -> None:
assert modulo(7, 2) == 1
19 changes: 19 additions & 0 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
from dotenv import load_dotenv
import pytest

# Load environment variables from .env file
load_dotenv()

# List of required environment variables
REQUIRED_ENV_VARS = ["SLACK_APP_TOKEN", "SLACK_BOT_TOKEN"]

def test_env_file_exists():
"""Test that the .env file exists."""
assert os.path.exists(".env"), "The .env file is missing."

@pytest.mark.parametrize("env_var", REQUIRED_ENV_VARS)
def test_env_var_exist(env_var):
value = os.getenv(env_var)
assert value, f'Missing definition of environment variable \'{env_var}\''

31 changes: 31 additions & 0 deletions tests/test_samples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest


def test_addition() -> None:
assert 2 + 2 == 4

def test_subtraction() -> None:
assert 5 - 3 == 2

def test_multiplication() -> None:
assert 3 * 3 == 9

def test_division() -> None:
assert 8 / 2 == 4

def test_string_equality() -> None:
assert "hello".upper() == "HELLO"

def test_list_append() -> None:
lst = [1, 2, 3]
lst.append(4)
assert lst == [1, 2, 3, 4]

def test_dictionary_key() -> None:
d = {"name": "Alice", "age": 30}
assert "name" in d
assert d["name"] == "Alice"

def test_raise_error() -> None:
with pytest.raises(ZeroDivisionError):
1 / 0
Loading