Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cdis/cs/courses/cs544/s25/main
  • zzhang2478/main
  • spark667/main
  • vijayprabhak/main
  • vijayprabhak/544-main
  • wyang338/cs-544-s-25
  • jmin39/main
7 results
Show changes
Commits on Source (116)
Showing
with 516 additions and 93 deletions
# main
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://git.doit.wisc.edu/cdis/cs/courses/cs544/s25/main.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://git.doit.wisc.edu/cdis/cs/courses/cs544/s25/main/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
# CSL VM
We have VMs from CSL. To access your VM, you'll need to be on the
uwmadison.vpn.wisc.edu VPN. Read about how to connect to it here:
https://it.wisc.edu/services/wiscvpn/.
You can SSH like this (note that your NETID is your username, and also part of the VM name):
```
ssh NETID@cs544-NETID.cs.wisc.edu
```
Your password is your regular UW password, as you would use to access https://my.wisc.edu.
If you don't like typing your password everytime, you could paste your
public key (from your laptop) in this file (on your VM):
`~/.ssh/authorized_keys`. Then your private key will be used to
authenticate with you SSH, and you won't need to type a password.
## Common Issues
* VPN access: this is supported by the DoIT Help Desk: https://kb.wisc.edu/helpdesk/
* Reboot: if you're VM got stuck (e.g., because you exhausted all available memory), you can reboot it here: https://proxmox.cs.wisc.edu. Find your VM and choose the "Reset" option.
# Read-only Access
We've opened up the `autobadger` tool in attempt to make things more visible to you and less of a "black box". We've done this by making the repository *read-only*, meaning you should be able to `git clone` the repo but not `git push` to it.
To start, navigate to a directory outside of any class project. I'd recommend cloning to the same directory as your projects.
```bash
git clone https://oauth2:glpat-CSTX_tgpf38eJHyUW213@git.doit.wisc.edu/cdis/cs/courses/cs544/s25/tools/autobadger.git
```
> **NOTE**: if you want to use this method throughout the semester, you'll need to `git pull` to get up-to-date code for each project.
Your folder structure should look something like
```
some-directory/
autobadger/
p1/
p2/
... # other projects
```
# Making Changes
You can change the code inside of `autobadger`. The only files that will be of interest to you are inside the `projects/` directory, i.e. `projects/*.py`). Your changes will be for debugging, i.e. `print()` or `breakpoint()` statements.
#### Using `pip`
For whatever project you're working on, you will need to *apply* any changes you make using `pip`
For example, assuming
- I'm working on `p2`
- in my `p2` directory
- and have my `venv` activated
I would do something like:
```bash
pip3 install ../autobadger/.
```
This would install and replace my local version of `autobadger` . Now when I run
```
autobadger --project=p2
```
I will see my changes in effect.
# Breakpoints
Since `breakpoint()` is less known and straightforward, I will teach about it here.
> **NOTE**: It is not required to use `breakpoint()`. You are also welcome to use `print()` instead. `breakpoint()` has a **steeper learning curve**, but may **help you iterate more quickly and save you time** once the basic concepts are well-understood.
### What is a breakpoint?
`breakpoint()` is a built-in function in Python and starts the **debugger** at the point where it is called. It allows developers to inspect variables, step through code, and debug interactively.
#### Simple Example:
```python
# Inside of /path/to/file.py
def calculate_sum(a, b):
breakpoint() # Debugger starts here
return a + b
calculate_sum(3, 5) # execute function
```
Adding a `breakpoint()` will pause execution, allowing you to inspect `a` and `b` before proceeding. I would see something like:
```
> /path/to/file.py(3)calculate_sum()
-> return a + b
```
in the terminal, which displays
1. the next line to be executed `return a + b`
2. `(3)calculate_sum()` tells me the line number and the function name (if applicable)
3. `/path/to/file.py` tells me the current file
### Navigating the debugger
While the Python debugger is active, you can use several commands to navigate through your program and investigate.
- `Variable name`: I can type any variable that is in scope and get it's value.
- Ex: Typing `a` in the previous example would return the *value* of `a`
- **NOTE**: if a variable name also coincides with a command keyword in the debugger, you may need to use `print(<variable_name>)` instead. `b` is one of those commands, so to print the value of `b` to the terminal, I would need to do `print(b)`:
- `Evaluation`: I can also evaluate statements (i.e. add two numbers)
```
In [3]: calculate_sum(3, 5)
> <ipython-input-2-443b6e8e0b0a>(3)calculate_sum()
-> return a + b
(Pdb) print(a)
3
(Pdb) print(b)
5
(Pdb) print(a + b)
8
```
- `n`: Steps to the next line of my program
- `c`: Continues execution of the program until the next breakpoint, or until the program ends.
- `s`: Steps *into* a function or method call
- `exit`: kills the debugger and ends the program
# An example
### Using breakpoints
Suppose I want to investigate `Q4` for `p2`. I can add `breakpoint()` statements to the Q4 test method for the `ProjectTwoTest` class.
Navigating to `projects/p2.py` inside of `autobadger`, I find:
```python
@graded(Q=4, points=10)
def test_simple_http(self) -> int | TestError:
address = self._test_cache_server("-cache-1")
if isinstance(address, TestError):
return address
r = requests.get(f"{address}/lookup/53706")
r.raise_for_status()
result = r.json()
if "addrs" not in result or "source" not in result:
return TestError(
message=f"Result body should be JSON with 'addrs' and 'source' fields, but got {result}.",
earned=5,
)
return 10
```
> Note: This is Q4 since I have `Q=4` in the decorator.
**I can edit this method by adding *breakpoints*!**
```python
@graded(Q=4, points=10)
def test_simple_http(self) -> int | TestError:
breakpoint()
address = self._test_cache_server("-cache-1")
if isinstance(address, TestError):
return address
r = requests.get(f"{address}/lookup/53706")
breakpoint()
r.raise_for_status()
result = r.json()
if "addrs" not in result or "source" not in result:
return TestError(
message=f"Result body should be JSON with 'addrs' and 'source' fields, but got {result}.",
earned=5,
)
return 10
```
Now, after I update with `pip` as mentioned above, I can run `autobadger --project=p2` and get:
```
> /Users/.../p2.py(103)test_simple_http()
-> address = self._test_cache_server("-cache-1")
```
Note that in this situation, typing `address` would give me an error cause it **not yet defined**:
```
(Pdb) address
*** NameError: name 'address' is not defined
```
###### Using `n` (next line)
`address` defined on the *next line*. So, I use the `n` command to step!
```
(Pdb) n
> /Users/.../p2.py(104)test_simple_http()
-> if isinstance(address, TestError):
(Pdb) address
'http://localhost:64879'
```
###### Using `s` (step into)
I could have also used `s` to *step into* `self._test_cache_server(...)` if I had wanted to investigate further:
```
> /Users/.../p2.py(103)test_simple_http()
-> address = self._test_cache_server("-cache-1")
(Pdb) s
--Call--
> /Users/.../p2.py(118)_test_cache_server()
-> def _test_cache_server(self, server_suffix: str) -> str | TestError:
# Now in a new method — _test_cache_server
(Pdb) n
> /Users/.../p2.py(119)_test_cache_server()
-> cache_server = [c for c in self.containers if c["Name"].endswith(server_suffix)]
```
###### Using `c` (continue)
I can also *continue* till the next breakpoint, which is quite convenient if you don't need to step over every line of code:
```
> /Users/.../p2.py(103)test_simple_http()
-> address = self._test_cache_server("-cache-1")
(Pdb) c
> /Users/.../p2.py(108)test_simple_http()
-> r.raise_for_status()
(Pdb) print(r.json())
{'addrs': [...], 'error': None, 'source': '...'}
```
Using `c` jumped from line `103` to line `108`, where I had my two breakpoints defined.
> **NOTE**: using `c` again would continue the Python program till the end of its execution since I have no other `breakpoint()` statements
\ No newline at end of file
File added
File added
File added
File added
File added
File added
File added
File added
FROM ubuntu:24.10
RUN apt-get update && \
apt-get install -y unzip python3 python3-pip
RUN pip3 install pandas==2.2.2 --break-system-packages
COPY test.py /test.py
CMD ["python3", "test.py"]
\ No newline at end of file
import pandas as pd
print(pd.Series([1,2,3]).sum())
import grpc
import math_pb2_grpc, math_pb2
channel = grpc.insecure_channel("localhost:5440")
stub = math_pb2_grpc.CalcStub(channel)
resp = stub.Mult(math_pb2.MultReq(x=3, y=4))
print(resp.result)
import grpc
import math_pb2_grpc, math_pb2
import sys
nums = [int(arg) for arg in sys.argv[1:]]
print(nums)
channel = grpc.insecure_channel("localhost:5440")
stub = math_pb2_grpc.CalcStub(channel)
resp = stub.MultMany(math_pb2.MultManyReq(nums=nums))
print(resp.result)
syntax = "proto3";
// PART 1: specify messages (with protobufs)
message MultManyReq {
repeated int32 nums = 1;
}
message MultReq {
int32 x = 1;
int32 y = 2;
}
message MultResp {
int32 result = 1;
}
// PART 2: specify RPC calls (gprc services)
service Calc {
// rpc FUNC_NAME(ARGS) returns (RESULT);
rpc Mult(MultReq) returns (MultResp);
rpc MultMany(MultManyReq) returns (MultResp);
}
\ No newline at end of file
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: math.proto
# Protobuf Python Version: 5.29.0
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
5,
29,
0,
'',
'math.proto'
)
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nmath.proto\"\x1b\n\x0bMultManyReq\x12\x0c\n\x04nums\x18\x01 \x03(\x05\"\x1f\n\x07MultReq\x12\t\n\x01x\x18\x01 \x01(\x05\x12\t\n\x01y\x18\x02 \x01(\x05\"\x1a\n\x08MultResp\x12\x0e\n\x06result\x18\x01 \x01(\x05\x32H\n\x04\x43\x61lc\x12\x1b\n\x04Mult\x12\x08.MultReq\x1a\t.MultResp\x12#\n\x08MultMany\x12\x0c.MultManyReq\x1a\t.MultRespb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'math_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
DESCRIPTOR._loaded_options = None
_globals['_MULTMANYREQ']._serialized_start=14
_globals['_MULTMANYREQ']._serialized_end=41
_globals['_MULTREQ']._serialized_start=43
_globals['_MULTREQ']._serialized_end=74
_globals['_MULTRESP']._serialized_start=76
_globals['_MULTRESP']._serialized_end=102
_globals['_CALC']._serialized_start=104
_globals['_CALC']._serialized_end=176
# @@protoc_insertion_point(module_scope)
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import warnings
import math_pb2 as math__pb2
GRPC_GENERATED_VERSION = '1.70.0'
GRPC_VERSION = grpc.__version__
_version_not_supported = False
try:
from grpc._utilities import first_version_is_lower
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
except ImportError:
_version_not_supported = True
if _version_not_supported:
raise RuntimeError(
f'The grpc package installed is at version {GRPC_VERSION},'
+ f' but the generated code in math_pb2_grpc.py depends on'
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
)
class CalcStub(object):
"""PART 2: specify RPC calls (gprc services)
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.Mult = channel.unary_unary(
'/Calc/Mult',
request_serializer=math__pb2.MultReq.SerializeToString,
response_deserializer=math__pb2.MultResp.FromString,
_registered_method=True)
self.MultMany = channel.unary_unary(
'/Calc/MultMany',
request_serializer=math__pb2.MultManyReq.SerializeToString,
response_deserializer=math__pb2.MultResp.FromString,
_registered_method=True)
class CalcServicer(object):
"""PART 2: specify RPC calls (gprc services)
"""
def Mult(self, request, context):
"""rpc FUNC_NAME(ARGS) returns (RESULT);
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def MultMany(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CalcServicer_to_server(servicer, server):
rpc_method_handlers = {
'Mult': grpc.unary_unary_rpc_method_handler(
servicer.Mult,
request_deserializer=math__pb2.MultReq.FromString,
response_serializer=math__pb2.MultResp.SerializeToString,
),
'MultMany': grpc.unary_unary_rpc_method_handler(
servicer.MultMany,
request_deserializer=math__pb2.MultManyReq.FromString,
response_serializer=math__pb2.MultResp.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'Calc', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('Calc', rpc_method_handlers)
# This class is part of an EXPERIMENTAL API.
class Calc(object):
"""PART 2: specify RPC calls (gprc services)
"""
@staticmethod
def Mult(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/Calc/Mult',
math__pb2.MultReq.SerializeToString,
math__pb2.MultResp.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
@staticmethod
def MultMany(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/Calc/MultMany',
math__pb2.MultManyReq.SerializeToString,
math__pb2.MultResp.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
import grpc
import math_pb2_grpc, math_pb2
from concurrent import futures
class Calculator(math_pb2_grpc.CalcServicer):
def Mult(self, request, context):
print("in mult")
result = request.x * request.y
return math_pb2.MultResp(result=result)
def MultMany(self, request, context):
print("in MultMany")
result = 1
for num in request.nums:
result *= num
return math_pb2.MultResp(result=result)
print("start server")
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), options=[("grpc.so_reuseport", 0)])
math_pb2_grpc.add_CalcServicer_to_server(Calculator(), server)
server.add_insecure_port("0.0.0.0:5440")
server.start()
server.wait_for_termination()
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y python3 python3-pip curl iproute2
COPY requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt --break-system-packages
CMD ["python3", "-m", "jupyterlab", "--no-browser", "--ip=0.0.0.0", "--port=600", "--allow-root", "--NotebookApp.token=''"]