Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
380255c
feat(cli): :sparkles: Rework CLI
LuisBlanche Dec 12, 2023
9b3a88f
feat(core): :sparkles: add Organisation Team and Project to APi Client
LuisBlanche Dec 12, 2023
d913379
build: :arrow_up: add new dependencies for cli
LuisBlanche Dec 12, 2023
951ed7c
fix(cli): :art: add a questionary prompt function
LuisBlanche Jan 13, 2024
1dbc62b
test(cli): :white_check_mark: pass tests CLI
LuisBlanche Jan 13, 2024
3677535
[507]:cleaning duplicate data
alencon Feb 29, 2024
124d0ee
[299]:Prevent duplicate entry on API
alencon Feb 29, 2024
17dbaf7
feat(cli): :sparkles: add more functionalities to python API client a…
LuisBlanche Mar 3, 2024
bb1be2d
feat(core): :sparkles: allows picking up API endpoint from conf file …
LuisBlanche Mar 3, 2024
4b67fe9
[#516] : CodeCarbon Dashboard content :
alencon Mar 18, 2024
0994802
feat(cli): :sparkles: allow to create a new custom configuration file…
LuisBlanche Mar 22, 2024
8b2c39b
feat(cli): :sparkles: Rework CLI
LuisBlanche Dec 12, 2023
1306879
feat(core): :sparkles: add Organisation Team and Project to APi Client
LuisBlanche Dec 12, 2023
cd7afe8
build: :arrow_up: add new dependencies for cli
LuisBlanche Dec 12, 2023
b52edab
fix(cli): :art: add a questionary prompt function
LuisBlanche Jan 13, 2024
3be9005
test(cli): :white_check_mark: pass tests CLI
LuisBlanche Jan 13, 2024
2e67fec
feat(cli): :sparkles: add more functionalities to python API client a…
LuisBlanche Mar 3, 2024
c09d39b
feat(core): :sparkles: allows picking up API endpoint from conf file …
LuisBlanche Mar 3, 2024
f86a666
feat(cli): :sparkles: allow to create a new custom configuration file…
LuisBlanche Mar 22, 2024
235a283
Merge branch 'feat/rework_cli' of https://github.com/mlco2/codecarbon…
LuisBlanche Mar 22, 2024
fd906df
feat(CLI): :sparkles: allow to use or modify existing config file or …
LuisBlanche Mar 22, 2024
ae09ce3
test(CLI): :white_check_mark: fix tests
LuisBlanche Mar 22, 2024
315542d
fix(CLI): :white_check_mark: use gihut action TEMP DIR
LuisBlanche Mar 22, 2024
bb1672c
ci(CLI): :green_heart: debu CI
LuisBlanche Mar 22, 2024
7818242
ci(CLI): :green_heart: try modifying tox ini
LuisBlanche Mar 22, 2024
d813861
fix(CLI): :white_check_mark: remove useless test that created a .code…
LuisBlanche Mar 22, 2024
f3f28c3
ci(CLI): :rewind: remove debug step
LuisBlanche Mar 22, 2024
3d8ab50
docs(CLI): :memo: test asciinema
LuisBlanche Mar 22, 2024
903e3f3
docs(CLI): :memo: fix code block
LuisBlanche Mar 22, 2024
8c3219e
[#299]:Fix API messages + add link for home page
alencon Mar 27, 2024
24a1c17
[#507]: Fix stored procedure raise notice
alencon Mar 27, 2024
56d4f96
empty line at end of file
Mar 29, 2024
3c9c740
[#516] : CodeCarbon Dashboard content :
alencon Apr 13, 2024
ff3ea09
Merge branch 'feat/rework_cli' into fix-database-mal
alencon Apr 15, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,6 @@ code_carbon.db
# Local file
emissions*.csv*
tests/test_data/rapl/*

#asciinema
*.cast
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ def add_organization(self, organization: OrganizationCreate) -> Organization:
description=organization.description,
api_key=generate_api_key(),
)

existing_organization = (
session.query(SqlModelOrganization).filter(SqlModelOrganization.name == organization.name).first()
)
if existing_organization:
raise HTTPException(
status_code=404,detail=f"the organization name {organization.name} already exists"
)

session.add(db_organization)
session.commit()
session.refresh(db_organization)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ def add_project(self, project: ProjectCreate):
description=project.description,
team_id=project.team_id,
)
existing_project = (
session.query(SqlModelProject)
.filter(SqlModelProject.name == project.name)
.filter(SqlModelProject.team_id == project.team_id)
.first()
)
if existing_project:
raise HTTPException(
status_code=404,detail=f"the project name {project.name} of team {project.team_id} already exists"
)

session.add(db_project)
session.commit()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ def add_team(self, team: TeamCreate) -> Team:
api_key=generate_api_key(),
organization_id=team.organization_id,
)
existing_team = (
session.query(SqlModelTeam)
.filter(SqlModelTeam.name == team.name)
.filter(SqlModelTeam.organization_id == team.organization_id)
.first()
)
if existing_team:
raise HTTPException(
status_code=404,detail=f"the team name {team.name} of organization {team.organization_id} already exists"
)


session.add(db_team)
session.commit()
session.refresh(db_team)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
spname : spcc_purgedata
goal : create a tempory table to display records where there are any information on runs and emissions
delete all records linked by their key referenced uuid from an organizations unused.
date : 20240222
version : 01
comment : 01 : initialize procedure spcc_purgeduplicatedata
created by : MARC ALENCON
modified by : MARC ALENCON
*/

/* Comments & Comments :
sample for camille organization to delete :
Delete from public.experiments
where project_id in ('6a121901-5fa6-4e37-9ad8-8ec86941feb5');

delete from public.projects
where team_id='d8e80b93-50f8-42fc-9280-650954415dbb';

delete from teams
where organization_id='92570ce9-1f90-4904-b9e6-80471963b740';

delete from organizations
where id ='92570ce9-1f90-4904-b9e6-80471963b740';
*/

CREATE OR REPLACE PROCEDURE public.spcc_purgeduplicatedata()
LANGUAGE 'plpgsql'
AS $BODY$

BEGIN -- Start of transaction

-- Création de la table temporaire
CREATE TEMP TABLE temp_table (
nb int ,
orga_id uuid ,
team_id uuid ,
project_id uuid ,
experiment_id uuid ,
run_id uuid ,
emission_id uuid
);


-- get distinct id from tables experiments , projects , teams , organizations
-- Insertion des données de la table source vers la table temporaire
INSERT INTO temp_table (nb, orga_id,team_id,project_id,experiment_id,run_id,emission_id )
SELECT count(*) as nb , o.id as orga_id,t.id as team_id, p.id as project_id, e.id as experiment_id , r.id as run_id , em.id as emission_id
from public.organizations o
left outer join public.teams t on o.id=t.organization_id
left outer join public.projects p on t.id = p.team_id
left outer join public.experiments e on p.id = e.project_id
left outer join public.runs r on e.id = r.experiment_id
left outer join public.emissions em on r.id = em.run_id
where r.id is null and em.id is null
group by o.id,t.id, p.id,e.id,r.id ,em.id;


/*
select count(*) from temp_table -- 752
select count(*) from experiments -- 1376 / 653
select count(*) from projects -- 41 /21
select count(*) from teams -- 26 /15
select count(*) from organizations --25 /12
*/

DO $$
DECLARE
row_data RECORD;
-- variables techniques .
a_count integer;
v_state TEXT;
v_msg TEXT;
v_detail TEXT;
v_hint TEXT;
v_context TEXT;


BEGIN
GET DIAGNOSTICS a_count = ROW_COUNT;
RAISE NOTICE '------- START -------';
FOR row_data IN SELECT orga_id, team_id,project_id,experiment_id,run_id,emission_id FROM temp_table LOOP

a_count = a_count +1;

--RAISE NOTICE '------- START -------';
RAISE NOTICE 'The rows affected by A=%',a_count;
RAISE NOTICE 'Delete experiments which contains any runs affected';
delete FROM public.experiments e
where e.id not in ( select r.experiment_id
from runs r
)
and e.project_id =row_data.project_id;


RAISE NOTICE '--------------';
RAISE NOTICE 'Delete projects which contains any experiments affected';

delete FROM public.projects p
where p.id not in ( select e.project_id
from experiments e
)
and p.team_id =row_data.team_id;


RAISE NOTICE '--------------';
RAISE NOTICE 'Delete teams which contains any project affected ';
DELETE from teams t
where t.id not in (select p.team_id from projects p)
and t.organization_id =row_data.orga_id;



RAISE NOTICE '--------------';
RAISE NOTICE 'Delete organizations which contains any teams affected';
DELETE from organizations o
where o.id not in (select t.organization_id from teams t )
and o.id = row_data.orga_id;

END LOOP;
RAISE NOTICE '-------- END ------';
EXCEPTION
WHEN others THEN

-- Handling error:Cancelled transaction when error produced
ROLLBACK;
get stacked diagnostics
v_state = returned_sqlstate,
v_msg = message_text,
v_detail = pg_exception_detail,
v_hint = pg_exception_hint,
v_context = pg_exception_context;
RAISE NOTICE E'Got exception :
state : %
message : %
detail : %
hint : %
context : % ', v_state, v_msg, v_detail, v_hint, v_context ;
END $$;

DROP TABLE temp_table;

COMMIT; -- end of transaction
END;
$BODY$;




1 change: 1 addition & 0 deletions codecarbon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
)

__all__ = ["EmissionsTracker", "OfflineEmissionsTracker", "track_emissions"]
__app_name__ = "codecarbon"
71 changes: 65 additions & 6 deletions codecarbon/cli/cli_utils.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
import configparser
from pathlib import Path
from typing import Optional

import typer
from rich.prompt import Confirm

def get_api_endpoint():
p = Path.cwd().resolve() / ".codecarbon.config"

def get_config(path: Optional[Path] = None):
p = path or Path.cwd().resolve() / ".codecarbon.config"

if p.exists():
config = configparser.ConfigParser()
config.read(str(p))
if "codecarbon" in config.sections():
d = dict(config["codecarbon"])
return d

else:
raise FileNotFoundError(
"No .codecarbon.config file found in the current directory."
)


def get_api_endpoint(path: Optional[Path] = None):
p = path or Path.cwd().resolve() / ".codecarbon.config"
if p.exists():
config = configparser.ConfigParser()
config.read(str(p))
if "codecarbon" in config.sections():
d = dict(config["codecarbon"])
if "api_endpoint" in d:
return d["api_endpoint"]
else:
with p.open("a") as f:
f.write("api_endpoint=https://api.codecarbon.io\n")
return "https://api.codecarbon.io"


def get_existing_local_exp_id():
p = Path.cwd().resolve() / ".codecarbon.config"
def get_existing_local_exp_id(path: Optional[Path] = None):
p = path or Path.cwd().resolve() / ".codecarbon.config"
if p.exists():
config = configparser.ConfigParser()
config.read(str(p))
Expand All @@ -25,8 +48,9 @@ def get_existing_local_exp_id():
return d["experiment_id"]


def write_local_exp_id(exp_id):
p = Path.cwd().resolve() / ".codecarbon.config"
def write_local_exp_id(exp_id, path: Optional[Path] = None):
p = path or Path.cwd().resolve() / ".codecarbon.config"

config = configparser.ConfigParser()
if p.exists():
config.read(str(p))
Expand All @@ -37,3 +61,38 @@ def write_local_exp_id(exp_id):

with p.open("w") as f:
config.write(f)


def overwrite_local_config(config_name, value, path: Optional[Path] = None):
p = path or Path.cwd().resolve() / ".codecarbon.config"

config = configparser.ConfigParser()
if p.exists():
config.read(str(p))
if "codecarbon" not in config.sections():
config.add_section("codecarbon")

config["codecarbon"][config_name] = value
with p.open("w") as f:
config.write(f)


def create_new_config_file():
typer.echo("Creating new config file")
file_path = typer.prompt(
"Where do you want to put your config file ?",
type=str,
default="./.codecarbon.config",
)
file_path = Path(file_path)
if not file_path.parent.exists():
create = Confirm.ask(
"Parent folder does not exist do you want to create it (and parents) ?"
)
if create:
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
with open(file_path, "w") as f:
f.write("[codecarbon]\n")
typer.echo(f"Config file created at {file_path}")
return file_path
Loading