graph-jsp-env


Namegraph-jsp-env JSON
Version 0.3.3 PyPI version JSON
download
home_page
SummaryA flexible enviorment for job shop scheduling using the disjunctive graph apporach.
upload_time2023-09-04 13:35:48
maintainer
docs_urlNone
authorAlexander Nasuta
requires_python>=3.9
licenseMIT License Copyright (c) 2022 Alexander Nasuta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            

<div id="top"></div>

<!-- PROJECT LOGO -->
<br />
<div align="center">
  <a href="https://cybernetics-lab.de/">
    <img src="https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/logo.png" alt="Logo" height="80">
  </a>

  <h1 align="center">
     Graph Job Shop Problem Gym Environment 
  </h1>

   <a>
    <img src="https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/graph_jsp_tikz.png" alt="Logo" height="180">
  </a>

</div>




# About The Project
An [Gymnasium Environment](https://gymnasium.farama.org/) implementation 
of the Job Shop Scheduling Problem (JSP) using the disjunctive graph approach.

- **Github**: https://github.com/Alexander-Nasuta/graph-jsp-env

- **PyPi**: https://pypi.org/project/graph-jsp-env/

This environment is inspired by the 
[The disjunctive graph machine representation of the job shop scheduling problem](https://www.sciencedirect.com/science/article/pii/S0377221799004865)
by Jacek Błażewicz and
[Learning to Dispatch for Job Shop Scheduling via Deep Reinforcement Learning](https://proceedings.neurips.cc/paper/2020/file/11958dfee29b6709f48a9ba0387a2431-Paper.pdf)
by Zhang, Cong, et al.

This environment does not explicitly include disjunctive edges, like specified by Jacek Błażewicz, 
only conjunctive edges. 
Additional information is saved in the edges and nodes, such that one could construct the disjunctive edges, so the is no loss in information.

This environment is more similar to the Zhang, Cong, et al. implementation.
Zhang, Cong, et al. seems to store exclusively time-information exclusively inside nodes 
(see Figure 2: Example of state transition) and no additional information inside the edges (like weights in the representation of Jacek Błażewicz).

The DisjunctiveGraphJssEnv uses the `networkx` library for graph structure and graph visualization.
It is highly configurable and offers various rendering options.

# Quick Start

Install the package with pip:
```
   pip install graph-jsp-env
```

## Minimal Working Example: Random Actions
The code below shows a minimal working example without any reinforcement learning 
```python
import numpy as np
from graph_jsp_env.disjunctive_graph_jsp_env import DisjunctiveGraphJspEnv

jsp = np.array([
    [[1, 2, 0],  # job 0
     [0, 2, 1]],  # job 1
    [[17, 12, 19],  # task durations of job 0
     [8, 6, 2]]  # task durations of job 1
])

env = DisjunctiveGraphJspEnv(
    jps_instance=jsp,
    perform_left_shift_if_possible=True, 
    normalize_observation_space=True,  # see documentation of DisjunctiveGraphJspEnv::get_state for more information
    flat_observation_space=True,  # see documentation of DisjunctiveGraphJspEnv::get_state for more information
    action_mode='task',  # alternative 'job'
    dtype='float32'  # dtype of the observation space
)

terminated = False
info = {}
for i in range(6):
    # get valid action mask. sample expects it to be a numpy array of type int8
    mask = np.array(env.valid_action_mask()).astype(np.int8)
    action = env.action_space.sample(mask=mask)
    state, reward, terminated, truncated, info = env.step(action)
    # chose the visualisation you want to see using the show parameter
    # console rendering
    env.render(show=["gantt_console", "graph_console"])
    
print(f"makespan: {info['makespan']}")
```
# Stable Baselines3
To run the example below you need to install the following packages:

```pip install stable_baselines3```

```pip install sb3_contrib```

It is recommended to use the `MaskablePPO` algorithm from the `sb3_contrib` package.

```python
import gymnasium as gym
import sb3_contrib
import numpy as np
import stable_baselines3 as sb3
from graph_jsp_env.disjunctive_graph_jsp_env import DisjunctiveGraphJspEnv
from graph_jsp_env.disjunctive_graph_logger import log
from sb3_contrib.common.wrappers import ActionMasker
from sb3_contrib.common.maskable.policies import MaskableActorCriticPolicy

jsp = np.array([
    [[1, 2, 0],  # job 0
     [0, 2, 1]],  # job 1
    [[17, 12, 19],  # task durations of job 0
     [8, 6, 2]]  # task durations of job 1
])

env = DisjunctiveGraphJspEnv(
    jps_instance=jsp,
    perform_left_shift_if_possible=True,
    normalize_observation_space=True,
    flat_observation_space=True,
    action_mode='task',  # alternative 'job'
)
env = sb3.common.monitor.Monitor(env)


def mask_fn(env: gym.Env) -> np.ndarray:
    return env.valid_action_mask()


env = ActionMasker(env, mask_fn)

model = sb3_contrib.MaskablePPO(MaskableActorCriticPolicy, env, verbose=1)

# Train the agent
log.info("training the model")
model.learn(total_timesteps=10_000)
```


### Visualisations
The environment offers multiple visualisation options.
There are four visualisations that can be mixed and matched:
- `gantt_window`: a gantt chart visualisation in a separate window
- `graph_window`: a graph visualisation in a separate window. This visualisation is computationally expensive.
- `gantt_console`: a gantt chart visualisation in the console
- `graph_console`: a graph visualisation in the console

The desired visualisation can be defaulted in the constructor of the environment with the argument `default_visualisations`.
To enable all visualisation specify `default_visualisations=["gantt_window", "gantt_console", "graph_window", "graph_console"]`.
The default visualisations are the used by the `render()` method if no visualisations are specified (using the `show` argument).

## Visualisation in OpenCV Window
This visualisation can enabled by setting `render_mode='window'` or setting the argument `default_visualisations=["gantt_window", "graph_window"]` in the constructor of the environment.
Additional parameters for OpencCV will be passed to the `cv2.imshow()` function.
Example:
```python
env.render(wait=1_000)  # render window closes automatically after 1 seconds
env.render(wait=None) # render window closes when any button is pressed (when the render window is focused)
```

![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/ft06_window_presi.gif)

## Console Visualisation 
This visualisation can enabled by setting `render_mode='window'` or setting the argument `default_visualisations=["gantt_console", "graph_console"]` in the constructor of the environment.
![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/ft06_console.gif)


## More Examples

Various examples can be found in the [graph-jsp-examples](https://github.com/Alexander-Nasuta/graph-jsp-examples) repo.

## Development 
The following sections are only relevant if you plan on further develop the environment and introduce code changes into 
the environment itself.

To run this Project locally on your machine follow the following steps:

1. Clone the repo
   ```sh
   git clone https://github.com/Alexander-Nasuta/graph-jsp-env.git
   ```
2. Install the python requirements_dev packages. `requirements_dev.txt` includes all the packages of
specified `requirements.txt` and some additional development packages like `mypy`, `pytext`, `tox` etc. 
    ```sh
   pip install -r requirements_dev.txt
   ```
3. Install the modules of the project locally. For more info have a look at 
[James Murphy's testing guide](https://www.youtube.com/watch?v=DhUpxWjOhME)
   ```sh
   pip install -e .
   ```

### Testing

For testing make sure that the dev dependencies are installed (`requirements_dev.txt`) and the models of this 
project are set up (i.e. you have run `pip install -e .`).  

Then you should be able to run

```sh
mypy src
```

```sh
flake8 src
```

```sh
pytest
```

or everthing at once using `tox`.

```sh
tox
```

### IDEA

I recommend to use [Pycharm](https://www.jetbrains.com/de-de/pycharm/).
Of course any code editor can be used instead (like [VS code](https://code.visualstudio.com/) 
or [Vim](https://github.com/vim/vim)).

This section goes over a few recommended step for setting up the Project properly inside [Pycharm](https://www.jetbrains.com/de-de/pycharm/).

#### PyCharm Setup
1. Mark the `src` directory as `Source Root`.
```
   right click on the 'src' -> 'Mark directory as' -> `Source Root`
```

2. Mark the `resources` directory as `Resource Root`.
```
   right click on the 'resources' -> 'Mark directory as' -> `Resource Root`
```

3. Mark the `tests` directory as `Test Source Root`.
```
   right click on the 'tests' -> 'Mark directory as' -> `Test Source Root`
```

afterwards your project folder should be colored in the following way:

<div align="center">
  <a>
    <img src="https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/mark_project_folders.png"  height="320">
  </a>
</div>

4. (optional) When running a script enable `Emulate terminal in output console`
```
Run (drop down) | Edit Configurations... | Configuration | ☑️ Emulate terminal in output console
```

![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/colored_logs_settings.png)


# License

Distributed under the MIT License. See `LICENSE.txt` for more information.

<!-- MARKDOWN LINKS & IMAGES todo: add Github, Linked in etc.-->
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
[screenshot]: resources/readme_images/screenshot.png



            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "graph-jsp-env",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "",
    "keywords": "",
    "author": "Alexander Nasuta",
    "author_email": "Alexander Nasuta <alexander.nasuta@ima.rwth-aachen.de>",
    "download_url": "https://files.pythonhosted.org/packages/3e/55/0c6600da029200575facd09b614e3bae30d021e1203eaa7ebc74981fa491/graph-jsp-env-0.3.3.tar.gz",
    "platform": "unix",
    "description": "\n\n<div id=\"top\"></div>\n\n<!-- PROJECT LOGO -->\n<br />\n<div align=\"center\">\n  <a href=\"https://cybernetics-lab.de/\">\n    <img src=\"https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/logo.png\" alt=\"Logo\" height=\"80\">\n  </a>\n\n  <h1 align=\"center\">\n     Graph Job Shop Problem Gym Environment \n  </h1>\n\n   <a>\n    <img src=\"https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/graph_jsp_tikz.png\" alt=\"Logo\" height=\"180\">\n  </a>\n\n</div>\n\n\n\n\n# About The Project\nAn [Gymnasium Environment](https://gymnasium.farama.org/) implementation \nof the Job Shop Scheduling Problem (JSP) using the disjunctive graph approach.\n\n- **Github**: https://github.com/Alexander-Nasuta/graph-jsp-env\n\n- **PyPi**: https://pypi.org/project/graph-jsp-env/\n\nThis environment is inspired by the \n[The disjunctive graph machine representation of the job shop scheduling problem](https://www.sciencedirect.com/science/article/pii/S0377221799004865)\nby Jacek B\u0142a\u017cewicz and\n[Learning to Dispatch for Job Shop Scheduling via Deep Reinforcement Learning](https://proceedings.neurips.cc/paper/2020/file/11958dfee29b6709f48a9ba0387a2431-Paper.pdf)\nby Zhang, Cong, et al.\n\nThis environment does not explicitly include disjunctive edges, like specified by Jacek B\u0142a\u017cewicz, \nonly conjunctive edges. \nAdditional information is saved in the edges and nodes, such that one could construct the disjunctive edges, so the is no loss in information.\n\nThis environment is more similar to the Zhang, Cong, et al. implementation.\nZhang, Cong, et al. seems to store exclusively time-information exclusively inside nodes \n(see Figure 2: Example of state transition) and no additional information inside the edges (like weights in the representation of Jacek B\u0142a\u017cewicz).\n\nThe DisjunctiveGraphJssEnv uses the `networkx` library for graph structure and graph visualization.\nIt is highly configurable and offers various rendering options.\n\n# Quick Start\n\nInstall the package with pip:\n```\n   pip install graph-jsp-env\n```\n\n## Minimal Working Example: Random Actions\nThe code below shows a minimal working example without any reinforcement learning \n```python\nimport numpy as np\nfrom graph_jsp_env.disjunctive_graph_jsp_env import DisjunctiveGraphJspEnv\n\njsp = np.array([\n    [[1, 2, 0],  # job 0\n     [0, 2, 1]],  # job 1\n    [[17, 12, 19],  # task durations of job 0\n     [8, 6, 2]]  # task durations of job 1\n])\n\nenv = DisjunctiveGraphJspEnv(\n    jps_instance=jsp,\n    perform_left_shift_if_possible=True, \n    normalize_observation_space=True,  # see documentation of DisjunctiveGraphJspEnv::get_state for more information\n    flat_observation_space=True,  # see documentation of DisjunctiveGraphJspEnv::get_state for more information\n    action_mode='task',  # alternative 'job'\n    dtype='float32'  # dtype of the observation space\n)\n\nterminated = False\ninfo = {}\nfor i in range(6):\n    # get valid action mask. sample expects it to be a numpy array of type int8\n    mask = np.array(env.valid_action_mask()).astype(np.int8)\n    action = env.action_space.sample(mask=mask)\n    state, reward, terminated, truncated, info = env.step(action)\n    # chose the visualisation you want to see using the show parameter\n    # console rendering\n    env.render(show=[\"gantt_console\", \"graph_console\"])\n    \nprint(f\"makespan: {info['makespan']}\")\n```\n# Stable Baselines3\nTo run the example below you need to install the following packages:\n\n```pip install stable_baselines3```\n\n```pip install sb3_contrib```\n\nIt is recommended to use the `MaskablePPO` algorithm from the `sb3_contrib` package.\n\n```python\nimport gymnasium as gym\nimport sb3_contrib\nimport numpy as np\nimport stable_baselines3 as sb3\nfrom graph_jsp_env.disjunctive_graph_jsp_env import DisjunctiveGraphJspEnv\nfrom graph_jsp_env.disjunctive_graph_logger import log\nfrom sb3_contrib.common.wrappers import ActionMasker\nfrom sb3_contrib.common.maskable.policies import MaskableActorCriticPolicy\n\njsp = np.array([\n    [[1, 2, 0],  # job 0\n     [0, 2, 1]],  # job 1\n    [[17, 12, 19],  # task durations of job 0\n     [8, 6, 2]]  # task durations of job 1\n])\n\nenv = DisjunctiveGraphJspEnv(\n    jps_instance=jsp,\n    perform_left_shift_if_possible=True,\n    normalize_observation_space=True,\n    flat_observation_space=True,\n    action_mode='task',  # alternative 'job'\n)\nenv = sb3.common.monitor.Monitor(env)\n\n\ndef mask_fn(env: gym.Env) -> np.ndarray:\n    return env.valid_action_mask()\n\n\nenv = ActionMasker(env, mask_fn)\n\nmodel = sb3_contrib.MaskablePPO(MaskableActorCriticPolicy, env, verbose=1)\n\n# Train the agent\nlog.info(\"training the model\")\nmodel.learn(total_timesteps=10_000)\n```\n\n\n### Visualisations\nThe environment offers multiple visualisation options.\nThere are four visualisations that can be mixed and matched:\n- `gantt_window`: a gantt chart visualisation in a separate window\n- `graph_window`: a graph visualisation in a separate window. This visualisation is computationally expensive.\n- `gantt_console`: a gantt chart visualisation in the console\n- `graph_console`: a graph visualisation in the console\n\nThe desired visualisation can be defaulted in the constructor of the environment with the argument `default_visualisations`.\nTo enable all visualisation specify `default_visualisations=[\"gantt_window\", \"gantt_console\", \"graph_window\", \"graph_console\"]`.\nThe default visualisations are the used by the `render()` method if no visualisations are specified (using the `show` argument).\n\n## Visualisation in OpenCV Window\nThis visualisation can enabled by setting `render_mode='window'` or setting the argument `default_visualisations=[\"gantt_window\", \"graph_window\"]` in the constructor of the environment.\nAdditional parameters for OpencCV will be passed to the `cv2.imshow()` function.\nExample:\n```python\nenv.render(wait=1_000)  # render window closes automatically after 1 seconds\nenv.render(wait=None) # render window closes when any button is pressed (when the render window is focused)\n```\n\n![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/ft06_window_presi.gif)\n\n## Console Visualisation \nThis visualisation can enabled by setting `render_mode='window'` or setting the argument `default_visualisations=[\"gantt_console\", \"graph_console\"]` in the constructor of the environment.\n![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/ft06_console.gif)\n\n\n## More Examples\n\nVarious examples can be found in the [graph-jsp-examples](https://github.com/Alexander-Nasuta/graph-jsp-examples) repo.\n\n## Development \nThe following sections are only relevant if you plan on further develop the environment and introduce code changes into \nthe environment itself.\n\nTo run this Project locally on your machine follow the following steps:\n\n1. Clone the repo\n   ```sh\n   git clone https://github.com/Alexander-Nasuta/graph-jsp-env.git\n   ```\n2. Install the python requirements_dev packages. `requirements_dev.txt` includes all the packages of\nspecified `requirements.txt` and some additional development packages like `mypy`, `pytext`, `tox` etc. \n    ```sh\n   pip install -r requirements_dev.txt\n   ```\n3. Install the modules of the project locally. For more info have a look at \n[James Murphy's testing guide](https://www.youtube.com/watch?v=DhUpxWjOhME)\n   ```sh\n   pip install -e .\n   ```\n\n### Testing\n\nFor testing make sure that the dev dependencies are installed (`requirements_dev.txt`) and the models of this \nproject are set up (i.e. you have run `pip install -e .`).  \n\nThen you should be able to run\n\n```sh\nmypy src\n```\n\n```sh\nflake8 src\n```\n\n```sh\npytest\n```\n\nor everthing at once using `tox`.\n\n```sh\ntox\n```\n\n### IDEA\n\nI recommend to use [Pycharm](https://www.jetbrains.com/de-de/pycharm/).\nOf course any code editor can be used instead (like [VS code](https://code.visualstudio.com/) \nor [Vim](https://github.com/vim/vim)).\n\nThis section goes over a few recommended step for setting up the Project properly inside [Pycharm](https://www.jetbrains.com/de-de/pycharm/).\n\n#### PyCharm Setup\n1. Mark the `src` directory as `Source Root`.\n```\n   right click on the 'src' -> 'Mark directory as' -> `Source Root`\n```\n\n2. Mark the `resources` directory as `Resource Root`.\n```\n   right click on the 'resources' -> 'Mark directory as' -> `Resource Root`\n```\n\n3. Mark the `tests` directory as `Test Source Root`.\n```\n   right click on the 'tests' -> 'Mark directory as' -> `Test Source Root`\n```\n\nafterwards your project folder should be colored in the following way:\n\n<div align=\"center\">\n  <a>\n    <img src=\"https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/mark_project_folders.png\"  height=\"320\">\n  </a>\n</div>\n\n4. (optional) When running a script enable `Emulate terminal in output console`\n```\nRun (drop down) | Edit Configurations... | Configuration | \u2611\ufe0f Emulate terminal in output console\n```\n\n![](https://github.com/Alexander-Nasuta/graph-jsp-env/raw/master/resources/readme_images/colored_logs_settings.png)\n\n\n# License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n<!-- MARKDOWN LINKS & IMAGES todo: add Github, Linked in etc.-->\n<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->\n[screenshot]: resources/readme_images/screenshot.png\n\n\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2022 Alexander Nasuta  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
    "summary": "A flexible enviorment for job shop scheduling using the disjunctive graph apporach.",
    "version": "0.3.3",
    "project_urls": {
        "Homepage": "https://github.com/Alexander-Nasuta/pypitemplate"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f7347420ee431c79d81211eabe04216d1346004b4ca76028feac0485818026c5",
                "md5": "e1ee696b6feabb77df6dce171791d3fd",
                "sha256": "808f30550d07ba9956cb3985cb3ff7dfd37826a4da34c232c5c3d813173e4eb0"
            },
            "downloads": -1,
            "filename": "graph_jsp_env-0.3.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e1ee696b6feabb77df6dce171791d3fd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 24137,
            "upload_time": "2023-09-04T13:35:39",
            "upload_time_iso_8601": "2023-09-04T13:35:39.580271Z",
            "url": "https://files.pythonhosted.org/packages/f7/34/7420ee431c79d81211eabe04216d1346004b4ca76028feac0485818026c5/graph_jsp_env-0.3.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3e550c6600da029200575facd09b614e3bae30d021e1203eaa7ebc74981fa491",
                "md5": "658e60af8092a31cb6a135f7d45591db",
                "sha256": "11f4f628a121237a9a073a65e568473d4c58aa83156e87e6221cff90a980411a"
            },
            "downloads": -1,
            "filename": "graph-jsp-env-0.3.3.tar.gz",
            "has_sig": false,
            "md5_digest": "658e60af8092a31cb6a135f7d45591db",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 28128,
            "upload_time": "2023-09-04T13:35:48",
            "upload_time_iso_8601": "2023-09-04T13:35:48.982267Z",
            "url": "https://files.pythonhosted.org/packages/3e/55/0c6600da029200575facd09b614e3bae30d021e1203eaa7ebc74981fa491/graph-jsp-env-0.3.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-04 13:35:48",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Alexander-Nasuta",
    "github_project": "pypitemplate",
    "github_not_found": true,
    "lcname": "graph-jsp-env"
}
        
Elapsed time: 0.29412s