ipygraph 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ipygraph/__init__.py +22 -0
- ipygraph/__main__.py +3 -0
- ipygraph/app.py +71 -0
- ipygraph/static/index.html +142 -0
- ipygraph/static/vendor/particles.min.js +8 -0
- ipygraph-0.1.0.dist-info/METADATA +43 -0
- ipygraph-0.1.0.dist-info/RECORD +11 -0
- ipygraph-0.1.0.dist-info/WHEEL +5 -0
- ipygraph-0.1.0.dist-info/entry_points.txt +2 -0
- ipygraph-0.1.0.dist-info/licenses/LICENSE +87 -0
- ipygraph-0.1.0.dist-info/top_level.txt +1 -0
ipygraph/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ipygraph
|
|
3
|
+
~~~~~~~~
|
|
4
|
+
A tiny desktop landing page (PyWebview + React + particles.js).
|
|
5
|
+
|
|
6
|
+
Import and call :pyfunc:`ipygraph.run` to open the window, or just
|
|
7
|
+
execute ``python -m ipygraph`` / run the ``ipygraph`` console-script.
|
|
8
|
+
|
|
9
|
+
:copyright: 2025 Your Name
|
|
10
|
+
:license: MIT, see LICENSE for details.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from importlib.metadata import version as _pkg_version
|
|
14
|
+
|
|
15
|
+
from .app import run # re-export for convenience
|
|
16
|
+
|
|
17
|
+
__all__ = ["run", "__version__"]
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
__version__: str = _pkg_version(__name__)
|
|
21
|
+
except Exception: # local editable install or missing metadata
|
|
22
|
+
__version__ = "0.0.0"
|
ipygraph/__main__.py
ADDED
ipygraph/app.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# ipygraph/app.py
|
|
2
|
+
"""
|
|
3
|
+
Launch the ipygraph landing-page window.
|
|
4
|
+
|
|
5
|
+
▫ Prefers Qt (fastest, fewest external deps) but gracefully falls back to
|
|
6
|
+
other back-ends if Qt isn’t available.
|
|
7
|
+
▫ Use python -m ipygraph --debug to keep Chromium DevTools open.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import importlib.resources as pkg_resources
|
|
13
|
+
import pathlib
|
|
14
|
+
import sys
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
|
|
17
|
+
import webview
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _locate_index_html() -> pathlib.Path:
|
|
21
|
+
"""Return the absolute path to static/index.html shipped in this package."""
|
|
22
|
+
return pkg_resources.files(__package__) / "static" / "index.html"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _choose_gui_order() -> Tuple[str, ...]:
|
|
26
|
+
"""
|
|
27
|
+
Return a tuple of back-ends to try in order.
|
|
28
|
+
First Qt, then GTK, then let pywebview decide.
|
|
29
|
+
"""
|
|
30
|
+
return ("qt", "gtk", "") # empty string → pywebview default search order
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def run() -> None:
|
|
34
|
+
debug = "--debug" in sys.argv
|
|
35
|
+
|
|
36
|
+
html_uri = _locate_index_html().as_uri()
|
|
37
|
+
|
|
38
|
+
# Build the window once; we’ll re-use it for each backend attempt.
|
|
39
|
+
window = webview.create_window(
|
|
40
|
+
title="ipygraph – Coming Soon",
|
|
41
|
+
url=html_uri,
|
|
42
|
+
width=1024,
|
|
43
|
+
height=768,
|
|
44
|
+
resizable=True,
|
|
45
|
+
zoomable=True,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
for gui in _choose_gui_order():
|
|
49
|
+
try:
|
|
50
|
+
webview.start(debug=debug, gui=gui, http_server=False)
|
|
51
|
+
# If we get here, that GUI worked → announce and exit the loop
|
|
52
|
+
backend = gui or webview.platform.name # name resolved by pywebview
|
|
53
|
+
print(f"[ipygraph] Using GUI backend: {backend}")
|
|
54
|
+
break
|
|
55
|
+
except (webview.exceptions.UnsupportedGUI, ModuleNotFoundError) as e:
|
|
56
|
+
print(f"[ipygraph] GUI '{gui or 'default'}' failed: {e}")
|
|
57
|
+
continue
|
|
58
|
+
else:
|
|
59
|
+
# If every backend fails, raise a helpful error
|
|
60
|
+
raise RuntimeError(
|
|
61
|
+
"ipygraph could not find a working GUI backend.\n"
|
|
62
|
+
"Install one of:\n"
|
|
63
|
+
" • Qt → conda install pyqt pyqtwebengine -c conda-forge\n"
|
|
64
|
+
" • GTK → conda install pygobject gtk3 -c conda-forge\n"
|
|
65
|
+
"or switch to a platform that bundles a backend."
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Enables: python -m ipygraph.app
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
run()
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>ipygraph | Coming Soon</title>
|
|
6
|
+
|
|
7
|
+
<!-- ============ Global layout & backdrop ============ -->
|
|
8
|
+
<style>
|
|
9
|
+
html, body {
|
|
10
|
+
margin: 0;
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
background: #000; /* fallback behind canvas */
|
|
15
|
+
}
|
|
16
|
+
#root {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
position: relative; /* context for centered text */
|
|
20
|
+
}
|
|
21
|
+
#particles-js {
|
|
22
|
+
position: fixed;
|
|
23
|
+
inset: 0;
|
|
24
|
+
z-index: 0; /* behind everything except body */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ============ Centered text styles ============ */
|
|
28
|
+
.center-text {
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 50%;
|
|
31
|
+
left: 50%;
|
|
32
|
+
transform: translate(-50%, -50%);
|
|
33
|
+
text-align: center;
|
|
34
|
+
z-index: 1; /* above canvas */
|
|
35
|
+
user-select: none;
|
|
36
|
+
}
|
|
37
|
+
.title {
|
|
38
|
+
margin: 0;
|
|
39
|
+
font: 900 5rem/1 "Segoe UI", sans-serif;
|
|
40
|
+
letter-spacing: .05em;
|
|
41
|
+
color: #fff;
|
|
42
|
+
text-shadow: 0 0 10px rgba(0,0,0,.6);
|
|
43
|
+
}
|
|
44
|
+
.subtitle {
|
|
45
|
+
font: 600 2rem/1.2 "Segoe UI", sans-serif;
|
|
46
|
+
color: #fff;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ============ Animated letters ============ */
|
|
50
|
+
@keyframes pulse {
|
|
51
|
+
0%,100% { transform: scale(1); }
|
|
52
|
+
50% { transform: scale(1.35); }
|
|
53
|
+
}
|
|
54
|
+
.letter {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
animation: pulse 1s ease-in-out infinite;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
|
|
61
|
+
<body>
|
|
62
|
+
<!-- Particle canvas -->
|
|
63
|
+
<div id="particles-js"></div>
|
|
64
|
+
|
|
65
|
+
<!-- React mount-point -->
|
|
66
|
+
<div id="root"></div>
|
|
67
|
+
|
|
68
|
+
<!-- ============ Libraries ============ -->
|
|
69
|
+
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
|
|
70
|
+
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
|
|
71
|
+
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
72
|
+
<!-- local copy of particles.js lives in static/vendor/ -->
|
|
73
|
+
<script src="vendor/particles.min.js"></script>
|
|
74
|
+
|
|
75
|
+
<!-- ============ React UI ============ -->
|
|
76
|
+
<script type="text/babel">
|
|
77
|
+
/* Animated subtitle component */
|
|
78
|
+
function ComingSoon({ text }) {
|
|
79
|
+
return (
|
|
80
|
+
<span className="subtitle">
|
|
81
|
+
{text.split("").map((ch, i) => (
|
|
82
|
+
<span
|
|
83
|
+
key={i}
|
|
84
|
+
className="letter"
|
|
85
|
+
style={{ animationDelay: `${i * 0.12}s` }}
|
|
86
|
+
>
|
|
87
|
+
{ch}
|
|
88
|
+
</span>
|
|
89
|
+
))}
|
|
90
|
+
</span>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Root component */
|
|
95
|
+
function App() {
|
|
96
|
+
return (
|
|
97
|
+
<div className="center-text">
|
|
98
|
+
<h1 className="title">ipyGraph</h1>
|
|
99
|
+
<ComingSoon text="coming soon" />
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<!-- ============ Particles init ============ -->
|
|
108
|
+
<script>
|
|
109
|
+
window.addEventListener('load', () => {
|
|
110
|
+
particlesJS('particles-js', {
|
|
111
|
+
particles: {
|
|
112
|
+
number: { value: 80, density: { enable: true, value_area: 800 } },
|
|
113
|
+
color: { value: '#ffffff' },
|
|
114
|
+
shape: { type: 'circle' },
|
|
115
|
+
opacity:{ value: 0.5 },
|
|
116
|
+
size: { value: 3 },
|
|
117
|
+
line_linked: {
|
|
118
|
+
enable: true,
|
|
119
|
+
distance: 150,
|
|
120
|
+
color: '#ffffff',
|
|
121
|
+
opacity: 0.4,
|
|
122
|
+
width: 1
|
|
123
|
+
},
|
|
124
|
+
move: { enable: true, speed: 2 }
|
|
125
|
+
},
|
|
126
|
+
interactivity: {
|
|
127
|
+
detect_on: 'canvas',
|
|
128
|
+
events: {
|
|
129
|
+
onhover: { enable: true, mode: 'repulse' },
|
|
130
|
+
onclick: { enable: true, mode: 'push' }
|
|
131
|
+
},
|
|
132
|
+
modes: {
|
|
133
|
+
repulse: { distance: 100, duration: 0.4 },
|
|
134
|
+
push: { particles_nb: 4 }
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
retina_detect: true
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
</script>
|
|
141
|
+
</body>
|
|
142
|
+
</html>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minified by jsDelivr using Terser v5.19.2.
|
|
3
|
+
* Original file: /npm/particles.js@2.0.0/particles.js
|
|
4
|
+
*
|
|
5
|
+
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
|
6
|
+
*/
|
|
7
|
+
var pJS=function(e,a){var t=document.querySelector("#"+e+" > .particles-js-canvas-el");this.pJS={canvas:{el:t,w:t.offsetWidth,h:t.offsetHeight},particles:{number:{value:400,density:{enable:!0,value_area:800}},color:{value:"#fff"},shape:{type:"circle",stroke:{width:0,color:"#ff0000"},polygon:{nb_sides:5},image:{src:"",width:100,height:100}},opacity:{value:1,random:!1,anim:{enable:!1,speed:2,opacity_min:0,sync:!1}},size:{value:20,random:!1,anim:{enable:!1,speed:20,size_min:0,sync:!1}},line_linked:{enable:!0,distance:100,color:"#fff",opacity:1,width:1},move:{enable:!0,speed:2,direction:"none",random:!1,straight:!1,out_mode:"out",bounce:!1,attract:{enable:!1,rotateX:3e3,rotateY:3e3}},array:[]},interactivity:{detect_on:"canvas",events:{onhover:{enable:!0,mode:"grab"},onclick:{enable:!0,mode:"push"},resize:!0},modes:{grab:{distance:100,line_linked:{opacity:1}},bubble:{distance:200,size:80,duration:.4},repulse:{distance:200,duration:.4},push:{particles_nb:4},remove:{particles_nb:2}},mouse:{}},retina_detect:!1,fn:{interact:{},modes:{},vendors:{}},tmp:{}};var i=this.pJS;a&&Object.deepExtend(i,a),i.tmp.obj={size_value:i.particles.size.value,size_anim_speed:i.particles.size.anim.speed,move_speed:i.particles.move.speed,line_linked_distance:i.particles.line_linked.distance,line_linked_width:i.particles.line_linked.width,mode_grab_distance:i.interactivity.modes.grab.distance,mode_bubble_distance:i.interactivity.modes.bubble.distance,mode_bubble_size:i.interactivity.modes.bubble.size,mode_repulse_distance:i.interactivity.modes.repulse.distance},i.fn.retinaInit=function(){i.retina_detect&&window.devicePixelRatio>1?(i.canvas.pxratio=window.devicePixelRatio,i.tmp.retina=!0):(i.canvas.pxratio=1,i.tmp.retina=!1),i.canvas.w=i.canvas.el.offsetWidth*i.canvas.pxratio,i.canvas.h=i.canvas.el.offsetHeight*i.canvas.pxratio,i.particles.size.value=i.tmp.obj.size_value*i.canvas.pxratio,i.particles.size.anim.speed=i.tmp.obj.size_anim_speed*i.canvas.pxratio,i.particles.move.speed=i.tmp.obj.move_speed*i.canvas.pxratio,i.particles.line_linked.distance=i.tmp.obj.line_linked_distance*i.canvas.pxratio,i.interactivity.modes.grab.distance=i.tmp.obj.mode_grab_distance*i.canvas.pxratio,i.interactivity.modes.bubble.distance=i.tmp.obj.mode_bubble_distance*i.canvas.pxratio,i.particles.line_linked.width=i.tmp.obj.line_linked_width*i.canvas.pxratio,i.interactivity.modes.bubble.size=i.tmp.obj.mode_bubble_size*i.canvas.pxratio,i.interactivity.modes.repulse.distance=i.tmp.obj.mode_repulse_distance*i.canvas.pxratio},i.fn.canvasInit=function(){i.canvas.ctx=i.canvas.el.getContext("2d")},i.fn.canvasSize=function(){i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i&&i.interactivity.events.resize&&window.addEventListener("resize",(function(){i.canvas.w=i.canvas.el.offsetWidth,i.canvas.h=i.canvas.el.offsetHeight,i.tmp.retina&&(i.canvas.w*=i.canvas.pxratio,i.canvas.h*=i.canvas.pxratio),i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i.particles.move.enable||(i.fn.particlesEmpty(),i.fn.particlesCreate(),i.fn.particlesDraw(),i.fn.vendors.densityAutoParticles()),i.fn.vendors.densityAutoParticles()}))},i.fn.canvasPaint=function(){i.canvas.ctx.fillRect(0,0,i.canvas.w,i.canvas.h)},i.fn.canvasClear=function(){i.canvas.ctx.clearRect(0,0,i.canvas.w,i.canvas.h)},i.fn.particle=function(e,a,t){if(this.radius=(i.particles.size.random?Math.random():1)*i.particles.size.value,i.particles.size.anim.enable&&(this.size_status=!1,this.vs=i.particles.size.anim.speed/100,i.particles.size.anim.sync||(this.vs=this.vs*Math.random())),this.x=t?t.x:Math.random()*i.canvas.w,this.y=t?t.y:Math.random()*i.canvas.h,this.x>i.canvas.w-2*this.radius?this.x=this.x-this.radius:this.x<2*this.radius&&(this.x=this.x+this.radius),this.y>i.canvas.h-2*this.radius?this.y=this.y-this.radius:this.y<2*this.radius&&(this.y=this.y+this.radius),i.particles.move.bounce&&i.fn.vendors.checkOverlap(this,t),this.color={},"object"==typeof e.value)if(e.value instanceof Array){var n=e.value[Math.floor(Math.random()*i.particles.color.value.length)];this.color.rgb=hexToRgb(n)}else null!=e.value.r&&null!=e.value.g&&null!=e.value.b&&(this.color.rgb={r:e.value.r,g:e.value.g,b:e.value.b}),null!=e.value.h&&null!=e.value.s&&null!=e.value.l&&(this.color.hsl={h:e.value.h,s:e.value.s,l:e.value.l});else"random"==e.value?this.color.rgb={r:Math.floor(256*Math.random())+0,g:Math.floor(256*Math.random())+0,b:Math.floor(256*Math.random())+0}:"string"==typeof e.value&&(this.color=e,this.color.rgb=hexToRgb(this.color.value));this.opacity=(i.particles.opacity.random?Math.random():1)*i.particles.opacity.value,i.particles.opacity.anim.enable&&(this.opacity_status=!1,this.vo=i.particles.opacity.anim.speed/100,i.particles.opacity.anim.sync||(this.vo=this.vo*Math.random()));var s={};switch(i.particles.move.direction){case"top":s={x:0,y:-1};break;case"top-right":s={x:.5,y:-.5};break;case"right":s={x:1,y:-0};break;case"bottom-right":s={x:.5,y:.5};break;case"bottom":s={x:0,y:1};break;case"bottom-left":s={x:-.5,y:1};break;case"left":s={x:-1,y:0};break;case"top-left":s={x:-.5,y:-.5};break;default:s={x:0,y:0}}i.particles.move.straight?(this.vx=s.x,this.vy=s.y,i.particles.move.random&&(this.vx=this.vx*Math.random(),this.vy=this.vy*Math.random())):(this.vx=s.x+Math.random()-.5,this.vy=s.y+Math.random()-.5),this.vx_i=this.vx,this.vy_i=this.vy;var r=i.particles.shape.type;if("object"==typeof r){if(r instanceof Array){var c=r[Math.floor(Math.random()*r.length)];this.shape=c}}else this.shape=r;if("image"==this.shape){var o=i.particles.shape;this.img={src:o.image.src,ratio:o.image.width/o.image.height},this.img.ratio||(this.img.ratio=1),"svg"==i.tmp.img_type&&null!=i.tmp.source_svg&&(i.fn.vendors.createSvgImg(this),i.tmp.pushing&&(this.img.loaded=!1))}},i.fn.particle.prototype.draw=function(){var e=this;if(null!=e.radius_bubble)var a=e.radius_bubble;else a=e.radius;if(null!=e.opacity_bubble)var t=e.opacity_bubble;else t=e.opacity;if(e.color.rgb)var n="rgba("+e.color.rgb.r+","+e.color.rgb.g+","+e.color.rgb.b+","+t+")";else n="hsla("+e.color.hsl.h+","+e.color.hsl.s+"%,"+e.color.hsl.l+"%,"+t+")";switch(i.canvas.ctx.fillStyle=n,i.canvas.ctx.beginPath(),e.shape){case"circle":i.canvas.ctx.arc(e.x,e.y,a,0,2*Math.PI,!1);break;case"edge":i.canvas.ctx.rect(e.x-a,e.y-a,2*a,2*a);break;case"triangle":i.fn.vendors.drawShape(i.canvas.ctx,e.x-a,e.y+a/1.66,2*a,3,2);break;case"polygon":i.fn.vendors.drawShape(i.canvas.ctx,e.x-a/(i.particles.shape.polygon.nb_sides/3.5),e.y-a/.76,2.66*a/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,1);break;case"star":i.fn.vendors.drawShape(i.canvas.ctx,e.x-2*a/(i.particles.shape.polygon.nb_sides/4),e.y-a/1.52,2*a*2.66/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,2);break;case"image":if("svg"==i.tmp.img_type)var s=e.img.obj;else s=i.tmp.img_obj;s&&i.canvas.ctx.drawImage(s,e.x-a,e.y-a,2*a,2*a/e.img.ratio)}i.canvas.ctx.closePath(),i.particles.shape.stroke.width>0&&(i.canvas.ctx.strokeStyle=i.particles.shape.stroke.color,i.canvas.ctx.lineWidth=i.particles.shape.stroke.width,i.canvas.ctx.stroke()),i.canvas.ctx.fill()},i.fn.particlesCreate=function(){for(var e=0;e<i.particles.number.value;e++)i.particles.array.push(new i.fn.particle(i.particles.color,i.particles.opacity.value))},i.fn.particlesUpdate=function(){for(var e=0;e<i.particles.array.length;e++){var a=i.particles.array[e];if(i.particles.move.enable){var t=i.particles.move.speed/2;a.x+=a.vx*t,a.y+=a.vy*t}if(i.particles.opacity.anim.enable&&(1==a.opacity_status?(a.opacity>=i.particles.opacity.value&&(a.opacity_status=!1),a.opacity+=a.vo):(a.opacity<=i.particles.opacity.anim.opacity_min&&(a.opacity_status=!0),a.opacity-=a.vo),a.opacity<0&&(a.opacity=0)),i.particles.size.anim.enable&&(1==a.size_status?(a.radius>=i.particles.size.value&&(a.size_status=!1),a.radius+=a.vs):(a.radius<=i.particles.size.anim.size_min&&(a.size_status=!0),a.radius-=a.vs),a.radius<0&&(a.radius=0)),"bounce"==i.particles.move.out_mode)var n={x_left:a.radius,x_right:i.canvas.w,y_top:a.radius,y_bottom:i.canvas.h};else n={x_left:-a.radius,x_right:i.canvas.w+a.radius,y_top:-a.radius,y_bottom:i.canvas.h+a.radius};if(a.x-a.radius>i.canvas.w?(a.x=n.x_left,a.y=Math.random()*i.canvas.h):a.x+a.radius<0&&(a.x=n.x_right,a.y=Math.random()*i.canvas.h),a.y-a.radius>i.canvas.h?(a.y=n.y_top,a.x=Math.random()*i.canvas.w):a.y+a.radius<0&&(a.y=n.y_bottom,a.x=Math.random()*i.canvas.w),"bounce"===i.particles.move.out_mode)(a.x+a.radius>i.canvas.w||a.x-a.radius<0)&&(a.vx=-a.vx),(a.y+a.radius>i.canvas.h||a.y-a.radius<0)&&(a.vy=-a.vy);if(isInArray("grab",i.interactivity.events.onhover.mode)&&i.fn.modes.grabParticle(a),(isInArray("bubble",i.interactivity.events.onhover.mode)||isInArray("bubble",i.interactivity.events.onclick.mode))&&i.fn.modes.bubbleParticle(a),(isInArray("repulse",i.interactivity.events.onhover.mode)||isInArray("repulse",i.interactivity.events.onclick.mode))&&i.fn.modes.repulseParticle(a),i.particles.line_linked.enable||i.particles.move.attract.enable)for(var s=e+1;s<i.particles.array.length;s++){var r=i.particles.array[s];i.particles.line_linked.enable&&i.fn.interact.linkParticles(a,r),i.particles.move.attract.enable&&i.fn.interact.attractParticles(a,r),i.particles.move.bounce&&i.fn.interact.bounceParticles(a,r)}}},i.fn.particlesDraw=function(){i.canvas.ctx.clearRect(0,0,i.canvas.w,i.canvas.h),i.fn.particlesUpdate();for(var e=0;e<i.particles.array.length;e++){i.particles.array[e].draw()}},i.fn.particlesEmpty=function(){i.particles.array=[]},i.fn.particlesRefresh=function(){cancelRequestAnimFrame(i.fn.checkAnimFrame),cancelRequestAnimFrame(i.fn.drawAnimFrame),i.tmp.source_svg=void 0,i.tmp.img_obj=void 0,i.tmp.count_svg=0,i.fn.particlesEmpty(),i.fn.canvasClear(),i.fn.vendors.start()},i.fn.interact.linkParticles=function(e,a){var t=e.x-a.x,n=e.y-a.y,s=Math.sqrt(t*t+n*n);if(s<=i.particles.line_linked.distance){var r=i.particles.line_linked.opacity-s/(1/i.particles.line_linked.opacity)/i.particles.line_linked.distance;if(r>0){var c=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+c.r+","+c.g+","+c.b+","+r+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(a.x,a.y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}},i.fn.interact.attractParticles=function(e,a){var t=e.x-a.x,n=e.y-a.y;if(Math.sqrt(t*t+n*n)<=i.particles.line_linked.distance){var s=t/(1e3*i.particles.move.attract.rotateX),r=n/(1e3*i.particles.move.attract.rotateY);e.vx-=s,e.vy-=r,a.vx+=s,a.vy+=r}},i.fn.interact.bounceParticles=function(e,a){var t=e.x-a.x,i=e.y-a.y;Math.sqrt(t*t+i*i)<=e.radius+a.radius&&(e.vx=-e.vx,e.vy=-e.vy,a.vx=-a.vx,a.vy=-a.vy)},i.fn.modes.pushParticles=function(e,a){i.tmp.pushing=!0;for(var t=0;t<e;t++)i.particles.array.push(new i.fn.particle(i.particles.color,i.particles.opacity.value,{x:a?a.pos_x:Math.random()*i.canvas.w,y:a?a.pos_y:Math.random()*i.canvas.h})),t==e-1&&(i.particles.move.enable||i.fn.particlesDraw(),i.tmp.pushing=!1)},i.fn.modes.removeParticles=function(e){i.particles.array.splice(0,e),i.particles.move.enable||i.fn.particlesDraw()},i.fn.modes.bubbleParticle=function(e){if(i.interactivity.events.onhover.enable&&isInArray("bubble",i.interactivity.events.onhover.mode)){var a=e.x-i.interactivity.mouse.pos_x,t=e.y-i.interactivity.mouse.pos_y,n=1-(l=Math.sqrt(a*a+t*t))/i.interactivity.modes.bubble.distance;function s(){e.opacity_bubble=e.opacity,e.radius_bubble=e.radius}if(l<=i.interactivity.modes.bubble.distance){if(n>=0&&"mousemove"==i.interactivity.status){if(i.interactivity.modes.bubble.size!=i.particles.size.value)if(i.interactivity.modes.bubble.size>i.particles.size.value){(c=e.radius+i.interactivity.modes.bubble.size*n)>=0&&(e.radius_bubble=c)}else{var r=e.radius-i.interactivity.modes.bubble.size,c=e.radius-r*n;e.radius_bubble=c>0?c:0}var o;if(i.interactivity.modes.bubble.opacity!=i.particles.opacity.value)if(i.interactivity.modes.bubble.opacity>i.particles.opacity.value)(o=i.interactivity.modes.bubble.opacity*n)>e.opacity&&o<=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=o);else(o=e.opacity-(i.particles.opacity.value-i.interactivity.modes.bubble.opacity)*n)<e.opacity&&o>=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=o)}}else s();"mouseleave"==i.interactivity.status&&s()}else if(i.interactivity.events.onclick.enable&&isInArray("bubble",i.interactivity.events.onclick.mode)){if(i.tmp.bubble_clicking){a=e.x-i.interactivity.mouse.click_pos_x,t=e.y-i.interactivity.mouse.click_pos_y;var l=Math.sqrt(a*a+t*t),v=((new Date).getTime()-i.interactivity.mouse.click_time)/1e3;v>i.interactivity.modes.bubble.duration&&(i.tmp.bubble_duration_end=!0),v>2*i.interactivity.modes.bubble.duration&&(i.tmp.bubble_clicking=!1,i.tmp.bubble_duration_end=!1)}function p(a,t,n,s,r){if(a!=t)if(i.tmp.bubble_duration_end)null!=n&&(o=a+(a-(s-v*(s-a)/i.interactivity.modes.bubble.duration)),"size"==r&&(e.radius_bubble=o),"opacity"==r&&(e.opacity_bubble=o));else if(l<=i.interactivity.modes.bubble.distance){if(null!=n)var c=n;else c=s;if(c!=a){var o=s-v*(s-a)/i.interactivity.modes.bubble.duration;"size"==r&&(e.radius_bubble=o),"opacity"==r&&(e.opacity_bubble=o)}}else"size"==r&&(e.radius_bubble=void 0),"opacity"==r&&(e.opacity_bubble=void 0)}i.tmp.bubble_clicking&&(p(i.interactivity.modes.bubble.size,i.particles.size.value,e.radius_bubble,e.radius,"size"),p(i.interactivity.modes.bubble.opacity,i.particles.opacity.value,e.opacity_bubble,e.opacity,"opacity"))}},i.fn.modes.repulseParticle=function(e){if(i.interactivity.events.onhover.enable&&isInArray("repulse",i.interactivity.events.onhover.mode)&&"mousemove"==i.interactivity.status){var a=e.x-i.interactivity.mouse.pos_x,t=e.y-i.interactivity.mouse.pos_y,n=Math.sqrt(a*a+t*t),s={x:a/n,y:t/n},r=clamp(1/(o=i.interactivity.modes.repulse.distance)*(-1*Math.pow(n/o,2)+1)*o*100,0,50),c={x:e.x+s.x*r,y:e.y+s.y*r};"bounce"==i.particles.move.out_mode?(c.x-e.radius>0&&c.x+e.radius<i.canvas.w&&(e.x=c.x),c.y-e.radius>0&&c.y+e.radius<i.canvas.h&&(e.y=c.y)):(e.x=c.x,e.y=c.y)}else if(i.interactivity.events.onclick.enable&&isInArray("repulse",i.interactivity.events.onclick.mode))if(i.tmp.repulse_finish||(i.tmp.repulse_count++,i.tmp.repulse_count==i.particles.array.length&&(i.tmp.repulse_finish=!0)),i.tmp.repulse_clicking){var o=Math.pow(i.interactivity.modes.repulse.distance/6,3),l=i.interactivity.mouse.click_pos_x-e.x,v=i.interactivity.mouse.click_pos_y-e.y,p=l*l+v*v,d=-o/p*1;p<=o&&function(){var a=Math.atan2(v,l);if(e.vx=d*Math.cos(a),e.vy=d*Math.sin(a),"bounce"==i.particles.move.out_mode){var t={x:e.x+e.vx,y:e.y+e.vy};(t.x+e.radius>i.canvas.w||t.x-e.radius<0)&&(e.vx=-e.vx),(t.y+e.radius>i.canvas.h||t.y-e.radius<0)&&(e.vy=-e.vy)}}()}else 0==i.tmp.repulse_clicking&&(e.vx=e.vx_i,e.vy=e.vy_i)},i.fn.modes.grabParticle=function(e){if(i.interactivity.events.onhover.enable&&"mousemove"==i.interactivity.status){var a=e.x-i.interactivity.mouse.pos_x,t=e.y-i.interactivity.mouse.pos_y,n=Math.sqrt(a*a+t*t);if(n<=i.interactivity.modes.grab.distance){var s=i.interactivity.modes.grab.line_linked.opacity-n/(1/i.interactivity.modes.grab.line_linked.opacity)/i.interactivity.modes.grab.distance;if(s>0){var r=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+r.r+","+r.g+","+r.b+","+s+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(i.interactivity.mouse.pos_x,i.interactivity.mouse.pos_y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}}},i.fn.vendors.eventsListeners=function(){"window"==i.interactivity.detect_on?i.interactivity.el=window:i.interactivity.el=i.canvas.el,(i.interactivity.events.onhover.enable||i.interactivity.events.onclick.enable)&&(i.interactivity.el.addEventListener("mousemove",(function(e){if(i.interactivity.el==window)var a=e.clientX,t=e.clientY;else a=e.offsetX||e.clientX,t=e.offsetY||e.clientY;i.interactivity.mouse.pos_x=a,i.interactivity.mouse.pos_y=t,i.tmp.retina&&(i.interactivity.mouse.pos_x*=i.canvas.pxratio,i.interactivity.mouse.pos_y*=i.canvas.pxratio),i.interactivity.status="mousemove"})),i.interactivity.el.addEventListener("mouseleave",(function(e){i.interactivity.mouse.pos_x=null,i.interactivity.mouse.pos_y=null,i.interactivity.status="mouseleave"}))),i.interactivity.events.onclick.enable&&i.interactivity.el.addEventListener("click",(function(){if(i.interactivity.mouse.click_pos_x=i.interactivity.mouse.pos_x,i.interactivity.mouse.click_pos_y=i.interactivity.mouse.pos_y,i.interactivity.mouse.click_time=(new Date).getTime(),i.interactivity.events.onclick.enable)switch(i.interactivity.events.onclick.mode){case"push":i.particles.move.enable||1==i.interactivity.modes.push.particles_nb?i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb,i.interactivity.mouse):i.interactivity.modes.push.particles_nb>1&&i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb);break;case"remove":i.fn.modes.removeParticles(i.interactivity.modes.remove.particles_nb);break;case"bubble":i.tmp.bubble_clicking=!0;break;case"repulse":i.tmp.repulse_clicking=!0,i.tmp.repulse_count=0,i.tmp.repulse_finish=!1,setTimeout((function(){i.tmp.repulse_clicking=!1}),1e3*i.interactivity.modes.repulse.duration)}}))},i.fn.vendors.densityAutoParticles=function(){if(i.particles.number.density.enable){var e=i.canvas.el.width*i.canvas.el.height/1e3;i.tmp.retina&&(e/=2*i.canvas.pxratio);var a=e*i.particles.number.value/i.particles.number.density.value_area,t=i.particles.array.length-a;t<0?i.fn.modes.pushParticles(Math.abs(t)):i.fn.modes.removeParticles(t)}},i.fn.vendors.checkOverlap=function(e,a){for(var t=0;t<i.particles.array.length;t++){var n=i.particles.array[t],s=e.x-n.x,r=e.y-n.y;Math.sqrt(s*s+r*r)<=e.radius+n.radius&&(e.x=a?a.x:Math.random()*i.canvas.w,e.y=a?a.y:Math.random()*i.canvas.h,i.fn.vendors.checkOverlap(e))}},i.fn.vendors.createSvgImg=function(e){var a=i.tmp.source_svg.replace(/#([0-9A-F]{3,6})/gi,(function(a,t,i,n){if(e.color.rgb)var s="rgba("+e.color.rgb.r+","+e.color.rgb.g+","+e.color.rgb.b+","+e.opacity+")";else s="hsla("+e.color.hsl.h+","+e.color.hsl.s+"%,"+e.color.hsl.l+"%,"+e.opacity+")";return s})),t=new Blob([a],{type:"image/svg+xml;charset=utf-8"}),n=window.URL||window.webkitURL||window,s=n.createObjectURL(t),r=new Image;r.addEventListener("load",(function(){e.img.obj=r,e.img.loaded=!0,n.revokeObjectURL(s),i.tmp.count_svg++})),r.src=s},i.fn.vendors.destroypJS=function(){cancelAnimationFrame(i.fn.drawAnimFrame),t.remove(),pJSDom=null},i.fn.vendors.drawShape=function(e,a,t,i,n,s){var r=n*s,c=n/s,o=180*(c-2)/c,l=Math.PI-Math.PI*o/180;e.save(),e.beginPath(),e.translate(a,t),e.moveTo(0,0);for(var v=0;v<r;v++)e.lineTo(i,0),e.translate(i,0),e.rotate(l);e.fill(),e.restore()},i.fn.vendors.exportImg=function(){window.open(i.canvas.el.toDataURL("image/png"),"_blank")},i.fn.vendors.loadImg=function(e){if(i.tmp.img_error=void 0,""!=i.particles.shape.image.src)if("svg"==e){var a=new XMLHttpRequest;a.open("GET",i.particles.shape.image.src),a.onreadystatechange=function(e){4==a.readyState&&(200==a.status?(i.tmp.source_svg=e.currentTarget.response,i.fn.vendors.checkBeforeDraw()):(console.log("Error pJS - Image not found"),i.tmp.img_error=!0))},a.send()}else{var t=new Image;t.addEventListener("load",(function(){i.tmp.img_obj=t,i.fn.vendors.checkBeforeDraw()})),t.src=i.particles.shape.image.src}else console.log("Error pJS - No image.src"),i.tmp.img_error=!0},i.fn.vendors.draw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type?i.tmp.count_svg>=i.particles.number.value?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):null!=i.tmp.img_obj?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame))},i.fn.vendors.checkBeforeDraw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type&&null==i.tmp.source_svg?i.tmp.checkAnimFrame=requestAnimFrame(check):(cancelRequestAnimFrame(i.tmp.checkAnimFrame),i.tmp.img_error||(i.fn.vendors.init(),i.fn.vendors.draw())):(i.fn.vendors.init(),i.fn.vendors.draw())},i.fn.vendors.init=function(){i.fn.retinaInit(),i.fn.canvasInit(),i.fn.canvasSize(),i.fn.canvasPaint(),i.fn.particlesCreate(),i.fn.vendors.densityAutoParticles(),i.particles.line_linked.color_rgb_line=hexToRgb(i.particles.line_linked.color)},i.fn.vendors.start=function(){isInArray("image",i.particles.shape.type)?(i.tmp.img_type=i.particles.shape.image.src.substr(i.particles.shape.image.src.length-3),i.fn.vendors.loadImg(i.tmp.img_type)):i.fn.vendors.checkBeforeDraw()},i.fn.vendors.eventsListeners(),i.fn.vendors.start()};function hexToRgb(e){e=e.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,(function(e,a,t,i){return a+a+t+t+i+i}));var a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return a?{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[3],16)}:null}function clamp(e,a,t){return Math.min(Math.max(e,a),t)}function isInArray(e,a){return a.indexOf(e)>-1}Object.deepExtend=function(e,a){for(var t in a)a[t]&&a[t].constructor&&a[t].constructor===Object?(e[t]=e[t]||{},arguments.callee(e[t],a[t])):e[t]=a[t];return e},window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)},window.cancelRequestAnimFrame=window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout,window.pJSDom=[],window.particlesJS=function(e,a){"string"!=typeof e&&(a=e,e="particles-js"),e||(e="particles-js");var t=document.getElementById(e),i="particles-js-canvas-el",n=t.getElementsByClassName(i);if(n.length)for(;n.length>0;)t.removeChild(n[0]);var s=document.createElement("canvas");s.className=i,s.style.width="100%",s.style.height="100%",null!=document.getElementById(e).appendChild(s)&&pJSDom.push(new pJS(e,a))},window.particlesJS.load=function(e,a,t){var i=new XMLHttpRequest;i.open("GET",a),i.onreadystatechange=function(a){if(4==i.readyState)if(200==i.status){var n=JSON.parse(a.currentTarget.response);window.particlesJS(e,n),t&&t()}else console.log("Error pJS - XMLHttpRequest status: "+i.status),console.log("Error pJS - File config not found")},i.send()};
|
|
8
|
+
//# sourceMappingURL=/sm/989ad3d344a46ad94354c16dc2512d23ddb937054ab7980adb822f74145374a7.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ipygraph
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Desktop landing page for ipygraph – PyWebview + React with particles.js
|
|
5
|
+
Author-email: Your Name <you@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: pywebview
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# ipygraph
|
|
14
|
+
|
|
15
|
+
> **A tiny desktop “coming soon” splash for the future *ipygraph* app,
|
|
16
|
+
> built with PyWebview, React 18, and a subtle particles.js background.**
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
* **Single-file front-end** – React & particles.js are pulled from CDNs; no local web-server needed.
|
|
25
|
+
* **Native window** – Ships as a PyPI package that opens a real desktop window (`chromium-embedded`).
|
|
26
|
+
* **One-liner launch** – `pip install ipygraph && ipygraph` (or `python -m ipygraph`).
|
|
27
|
+
* **Hack-friendly** – Pass `--debug` to open Chromium DevTools and live-edit the UI.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install ipygraph
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
| Audience | Cost | Modification Allowed? | Notes |
|
|
39
|
+
|----------|------|-----------------------|-------|
|
|
40
|
+
| **Individual (personal / hobby)** | **Free** | **No** | Private, non-commercial use only |
|
|
41
|
+
| **Commercial / organizational** | **Paid** | Only if expressly granted in a separate contract | Contact <you@example.com> |
|
|
42
|
+
|
|
43
|
+
Full terms in [LICENSE](LICENSE).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ipygraph/__init__.py,sha256=34LNp6X6i9uMsp-oR-rfCGXuXZpb8OySLWQwiC-JLPo,581
|
|
2
|
+
ipygraph/__main__.py,sha256=K98BO7GszyT6TPeQmNevXJtJh8StR-HG0rr8GnOIaSc,28
|
|
3
|
+
ipygraph/app.py,sha256=QcMnRbEZY0Tmm6YCnGNJeF8IrRqek1qroSn-08_jAmc,2231
|
|
4
|
+
ipygraph/static/index.html,sha256=3QDth6oWaFSqcaNfcdmOY_no3MnVO1K0c7ik6YBTnhA,3779
|
|
5
|
+
ipygraph/static/vendor/particles.min.js,sha256=4CVKTLmrkrCVvcp7cJhhBq7-PUdDjbXA3x3HI_cudR0,23016
|
|
6
|
+
ipygraph-0.1.0.dist-info/licenses/LICENSE,sha256=cfXzmTgBL_1IsjWBCUFmcnM8pu2H8gqybWJBAoq1Nek,6736
|
|
7
|
+
ipygraph-0.1.0.dist-info/METADATA,sha256=AKY-VyZn3aDmWuJYNWuNKmu_v25QJvUpCCQXVnwTFUM,1413
|
|
8
|
+
ipygraph-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
ipygraph-0.1.0.dist-info/entry_points.txt,sha256=vg5BYGG618QreRrkQJcuwVcBZsFGF9TF_LgPcDoyHYU,46
|
|
10
|
+
ipygraph-0.1.0.dist-info/top_level.txt,sha256=25M51U791Q4ek7OUVgI9X5CDXECuXJqNXuE3Hylx5eg,9
|
|
11
|
+
ipygraph-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
IPYGRAPH COMMUNITY & COMMERCIAL LICENSE (NO-MODIFICATION)
|
|
2
|
+
Version 1.1 — 22 June 2025
|
|
3
|
+
© 2025 Your Name. All rights reserved.
|
|
4
|
+
|
|
5
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
Preamble
|
|
7
|
+
This license grants two sets of rights:
|
|
8
|
+
▸ “Personal Use” — free of charge for natural persons, strictly
|
|
9
|
+
non-commercial, **without the right to modify** the Software.
|
|
10
|
+
▸ “Commercial Use” — requires a paid agreement for any organizational
|
|
11
|
+
or revenue-generating use, also **without the right to modify** the
|
|
12
|
+
Software unless expressly permitted in that separate contract.
|
|
13
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
DEFINITIONS
|
|
16
|
+
-----------
|
|
17
|
+
“Software” means all source code, binaries, assets, and documentation
|
|
18
|
+
contained in the ‘ipygraph’ package and any derivative
|
|
19
|
+
distribution of it made by the Licensor.
|
|
20
|
+
|
|
21
|
+
“Personal Use” means use by an individual natural person exclusively for
|
|
22
|
+
private, non-commercial purposes and **not** on behalf of
|
|
23
|
+
any Commercial Entity.
|
|
24
|
+
|
|
25
|
+
“Commercial Entity” means any corporation, partnership, sole trader,
|
|
26
|
+
government agency, non-profit, academic institution,
|
|
27
|
+
or any individual using the Software in connection
|
|
28
|
+
with goods or services offered for monetary or other
|
|
29
|
+
consideration.
|
|
30
|
+
|
|
31
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
SECTION 1 — PERSONAL USE LICENSE (FREE, NO MODIFICATION)
|
|
33
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
34
|
+
1.1 Grant. Subject to compliance with this License, the Licensor grants any
|
|
35
|
+
natural person (“User”) a worldwide, royalty-free, non-exclusive,
|
|
36
|
+
revocable license to **install and run** the unmodified Software on an
|
|
37
|
+
unlimited number of devices for Personal Use.
|
|
38
|
+
|
|
39
|
+
1.2 Restrictions. The User SHALL NOT:
|
|
40
|
+
(a) modify, translate, reverse-engineer, decompile, or disassemble the
|
|
41
|
+
Software, in whole or in part;
|
|
42
|
+
(b) redistribute, sublicense, sell, rent, lease, lend, or otherwise
|
|
43
|
+
make the Software available to third parties;
|
|
44
|
+
(c) use the Software for any commercial, professional, or revenue-
|
|
45
|
+
generating activity.
|
|
46
|
+
|
|
47
|
+
Any breach of 1.2 immediately terminates this Personal Use License.
|
|
48
|
+
|
|
49
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
50
|
+
SECTION 2 — COMMERCIAL USE (PAID LICENSE REQUIRED)
|
|
51
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
52
|
+
2.1 No rights are granted for Commercial Use under this document. A
|
|
53
|
+
separate written Commercial License agreement with the Licensor and
|
|
54
|
+
full payment of the applicable fee are required **before** any
|
|
55
|
+
commercial, organizational, or revenue-generating use.
|
|
56
|
+
|
|
57
|
+
2.2 The Commercial License may, at the Licensor’s discretion, grant limited
|
|
58
|
+
rights to modify the Software; any such rights must be explicitly
|
|
59
|
+
stated in that separate agreement.
|
|
60
|
+
|
|
61
|
+
For inquiries: <you@example.com>
|
|
62
|
+
|
|
63
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
SECTION 3 — NO SURRENDER OF RIGHTS
|
|
65
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
66
|
+
All rights not expressly granted herein are reserved by the Licensor.
|
|
67
|
+
|
|
68
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
69
|
+
SECTION 4 — DISCLAIMER OF WARRANTY
|
|
70
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
72
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
73
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
74
|
+
LICENSOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
75
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
76
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
77
|
+
|
|
78
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
SECTION 5 — TERMINATION
|
|
80
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
81
|
+
Violation of any term of this License automatically terminates all rights
|
|
82
|
+
granted. Upon termination, the Licensee must cease using and destroy all
|
|
83
|
+
copies of the Software.
|
|
84
|
+
|
|
85
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
86
|
+
END OF LICENSE
|
|
87
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ipygraph
|