Skip to content
Merged
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
154 changes: 154 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

# CGraph Code of Conduct

## Coding Guidelines

### C++
Please ensure your code follows the CGraph coding guidelines. Consistent coding style helps maintain the codebase.

Based on Google style guide, with some differences(perhaps):

- Function naming: First letter lowercase, camelCase
```
int getCode() {
return 0;
}
```

- Class and struct naming: First letter uppercase, camelCase
```
class MyClass {
}

struct MyStruct {
}
```

- Variable naming: First letter lowercase, camelCase
```
int myVar = 0;
```

- Member variable naming: First letter lowercase, words connected by underscore, ends with underscore
```
class MyClass {
int my_var_;
}

struct MyStruct {
int my_var_;
}
```

- Macro naming: All uppercase, words connected by underscore
```
#define MY_MACRO (1)
```

- Enum naming: All uppercase, words connected by underscore
```
enum MyEnum {
MY_ENUM_VALUE1,
MY_ENUM_VALUE2,
MY_ENUM_VALUE3,
};
```

### Python

Based on the Google Python Style Guide, the basic requirements are as follows:

1. Files and Encoding
- **File Encoding**: Files should be encoded in UTF-8 and usually do not need an encoding declaration at the top of the file (Python 3 uses UTF-8 by default).
- **File Naming**: First letter uppercase, camelCase, e.g., `MyModule.py`.

2. Comments
- **Module Comments**: Each module should start with a module-level docstring describing the module's purpose, functionality, and main classes or functions. For example:
```python
"""
This module provides utility functions for handling strings.

It includes functions for string formatting, splitting, and joining.
"""
```
- **Function and Method Comments**: Functions and methods also require docstrings explaining their purpose, parameters, return values, and possible exceptions. For example:
```python
def addNumbers(a: int, b: int):
"""
Add two numbers together.

Args:
a (int): The first number.
b (int): The second number.

Returns:
int: The sum of a and b.
"""
return a + b
```
- **Inline Comments**: Use inline comments in the code to explain complex or non-intuitive parts, but don't overuse them. Comments should be concise and clear.

3. Classes and Objects
- **Class Naming**: Class names should use CapWords convention, e.g., `MyClass`.
- **Class Docstrings**: Classes should include a docstring describing their purpose and main functionality.
```python
class MyClass:
"""
A simple class that represents a person.

Attributes:
name (str): The name of the person.
age (int): The age of the person.
"""
def __init__(self, name: str, age: int):
self.name = name
self.age = age

def getInfo(self):
"""
Get the person's information.

Returns:
str: A string containing the person's name and age.
"""
return f"Name: {self.name}, Age: {self.age}"
```
- **Member Variable and Method Naming**: Member variables and method names should use lowercase with words separated by underscores, e.g., `my_variable` and `my_method`.

4. Functions and Methods
- **Function Naming**: Function names should use lowercase first letter, camelCase, e.g., `checkResult()`.
- **Parameter Naming**: Parameter names should also use lowercase first letter, camelCase, and be descriptive, e.g., `myResultValue`.
- **Function Length**: Functions should be kept short and focused on a single task. Avoid excessively long functions.

5. Code Layout
- **Indentation**: Use 4 spaces for indentation, not tabs.
- **Line Length**: Limit each line of code to a maximum of 120 characters. If it exceeds, break the line while maintaining code readability. Usually break after operators. For example:
```python
result = getResult(arg1, arg2,
arg3, arg4)
```
- **Blank Lines**: Use blank lines to separate logical sections, e.g., two blank lines between functions and classes, one blank line between methods within a class.

6. Import Statements
- **Import Order**: Group import statements in the order of standard library, third-party libraries, and local modules, with a blank line between each group. For example:
```python
import os
import sys

import requests

from MyModule import MyClass
```
- **Avoid Wildcard Imports**: Avoid using wildcard imports like `from module import *` as they can lead to naming conflicts and reduced code readability.

7. Exception Handling
- **Specific Exception Types**: When catching exceptions, specify the exact exception type instead of using a generic `except` statement. For example:
```python
try:
result = 1 / 0
except ZeroDivisionError:
print("Division by zero occurred.")
```

8. Testing
- **Write Unit Tests**: Write unit tests for your code to ensure correctness and stability. You can use Python's `unittest` or `pytest` testing frameworks.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ if __name__ == '__main__':
* 提供 Python 和 C++ 混合编程功能
* 提供 Python 打包功能,支持 `pip3 install PyCGraph` 安装

[2025.05.05 - v3.1.1 - Chunel]
* 提供 `CODE_OF_CONDUCT.md` 文档

</details>

------------
Expand Down
120 changes: 55 additions & 65 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

## 1. Introduction

CGraph, short for <b>C</b>olor <b>Graph</b>, is a cross-platform DAG computing framework without any third-party dependencies. With the scheduling via `GPipeline`, the purpose of sequential and concurrent executing elements is realized.
CGraph, short for <b>C</b>olor <b>Graph</b>, is a cross-platform DAG computing framework. It is written by C++11 without any third-party dependencies, Python APIs are also supported.

You only need to inherit `GNode` class, implement the `run()` method in the subclass, and set the dependencies as needed to achieve the graphical execution of tasks.
With the scheduling via `GPipeline`, the purpose of sequential and concurrent executing elements is realized. You only need to inherit `GNode` class, implement the `run()` method in the subclass, and set the dependencies as needed to achieve the graphical execution of tasks.

At the same time, you can also control the graph conditional judgment, loop or concurrent execution logic by setting various `GGroup`s, which containing multi-node information by themselves.

Expand All @@ -29,94 +29,84 @@ You can transfer your params in many scenes. It is also possible to extend the f
![CGraph Skeleton](https://github.com/ChunelFeng/CGraph/blob/main/doc/image/CGraph%20Skeleton.jpg)
<br>

## 2. Compile
* This project supports MacOS, Linux, and Windows systems without any third-party dependencies. C++11 is default and lowest version, C++17 is recommended.

* For developers using `CLion` as IDE within all platform, open the `CMakeLists.txt` file as project to compile.

* Developers on Windows system, using `Visual Studio`(2013 version at least) as IDE, with cmake, enter commands as flowers to build `CGraph.sln` file.
```shell
$ git clone https://github.com/ChunelFeng/CGraph.git
$ cd CGraph
$ cmake . -Bbuild
```

* Developers on MacOS system, using `Xcode` as IDE, with cmake, enter commands as flowers to build `CGraph.xcodeproj` file.
```shell
$ git clone https://github.com/ChunelFeng/CGraph.git
$ cd CGraph
$ mkdir build && cd build
$ cmake .. -G Xcode
```

* Developers on Linux system, enter commands as flowers to compile.
```shell
$ git clone https://github.com/ChunelFeng/CGraph.git
$ cd CGraph
$ cmake . -Bbuild
$ cd build
$ make -j8
```

* Compile online, enter [CGraph env online](https://gitpod.io/#/github.com/ChunelFeng/CGraph), log in with your Github id, enter commands as flowers to compile and run your first tutorial.
```shell
$ sudo apt-get install cmake -y
$ ./CGraph-build.sh
$ ./build/tutorial/T00-HelloCGraph
```

## 3. Demo

#### MyNode.h
## 2. Demo

> C++ version

```cpp
#include "CGraph.h"

class MyNode1 : public CGraph::GNode {
using namespace CGraph;

class MyNode1 : public GNode {
public:
CStatus run () override {
CStatus status;
printf("[%s], Sleep for 1 second ... \n", this->getName().c_str());
CStatus run() override {
printf("[%s], sleep for 1 second ...\n", this->getName().c_str());
CGRAPH_SLEEP_SECOND(1)
return status;
return CStatus();
}
};


class MyNode2 : public CGraph::GNode {
class MyNode2 : public GNode {
public:
CStatus run () override {
CStatus status;
printf("[%s], Sleep for 1 second ... \n", this->getName().c_str());
CStatus run() override {
printf("[%s], sleep for 2 second ...\n", this->getName().c_str());
CGRAPH_SLEEP_SECOND(2)
return status;
return CStatus();
}
};
```

#### main.cpp
```cpp
#include "MyNode.h"

using namespace CGraph;

int main() {
/* build a pipeline */
GPipelinePtr pipeline = GPipelineFactory::create();
GElementPtr a, b, c, d = nullptr;

/* register node with dependency info */
pipeline->registerGElement<MyNode1>(&a, {}, "nodeA"); // register nodeA with no dependency
pipeline->registerGElement<MyNode2>(&b, {a}, "nodeB"); // b depends a
pipeline->registerGElement<MyNode1>(&a, {}, "nodeA");
pipeline->registerGElement<MyNode2>(&b, {a}, "nodeB");
pipeline->registerGElement<MyNode1>(&c, {a}, "nodeC");
pipeline->registerGElement<MyNode2>(&d, {b, c}, "nodeD"); // d depends b and c
pipeline->registerGElement<MyNode2>(&d, {b, c}, "nodeD");

pipeline->process();

/* run dag pipeline */
status = pipeline->process();
GPipelineFactory::remove(pipeline);

return 0;
}
```

![CGraph Demo](https://github.com/ChunelFeng/CGraph/blob/main/doc/image/CGraph%20Demo.jpg)
<br>
As is shown on the picture, run `a` firstly. Then, run `b` and `c` parallelized. Run `d` at last after `b` and `c` finished.

> Python version
```python
import time
from datetime import datetime

from PyCGraph import GNode, GPipeline, CStatus


class MyNode1(GNode):
def run(self):
print("[{0}] {1}, enter MyNode1 run function. Sleep for 1 second ... ".format(datetime.now(), self.getName()))
time.sleep(1)
return CStatus()

class MyNode2(GNode):
def run(self):
print("[{0}] {1}, enter MyNode2 run function. Sleep for 2 second ... ".format(datetime.now(), self.getName()))
time.sleep(2)
return CStatus()


if __name__ == '__main__':
pipeline = GPipeline()
a, b, c, d = MyNode1(), MyNode2(), MyNode1(), MyNode2()

pipeline.registerGElement(a, set(), "nodeA")
pipeline.registerGElement(b, {a}, "nodeB")
pipeline.registerGElement(c, {a}, "nodeC")
pipeline.registerGElement(d, {b, c}, "nodeD")

pipeline.process()
```
Loading