cobra-oop 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.
- cobra/__init__.py +58 -0
- cobra/base.py +52 -0
- cobra/decorators.py +61 -0
- cobra/exceptions.py +65 -0
- cobra/fields.py +69 -0
- cobra/utils.py +53 -0
- cobra_oop-0.1.0.dist-info/METADATA +169 -0
- cobra_oop-0.1.0.dist-info/RECORD +11 -0
- cobra_oop-0.1.0.dist-info/WHEEL +5 -0
- cobra_oop-0.1.0.dist-info/licenses/LICENSE +21 -0
- cobra_oop-0.1.0.dist-info/top_level.txt +1 -0
cobra/__init__.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
COBRA
|
|
3
|
+
=====
|
|
4
|
+
|
|
5
|
+
Comprehensive Object-Based Runtime Architecture
|
|
6
|
+
|
|
7
|
+
Optional runtime-enforced OOP features for Python.
|
|
8
|
+
|
|
9
|
+
Author: Vishnu Swaroop
|
|
10
|
+
Version: 0.1.0
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .base import CobraObject
|
|
14
|
+
from .decorators import (
|
|
15
|
+
private,
|
|
16
|
+
protected,
|
|
17
|
+
public,
|
|
18
|
+
final,
|
|
19
|
+
override,
|
|
20
|
+
)
|
|
21
|
+
from .exceptions import (
|
|
22
|
+
CobraError,
|
|
23
|
+
PrivateAccessError,
|
|
24
|
+
ProtectedAccessError,
|
|
25
|
+
FinalMethodError,
|
|
26
|
+
OverrideError,
|
|
27
|
+
CobraConfigurationError,
|
|
28
|
+
)
|
|
29
|
+
from .fields import (
|
|
30
|
+
PrivateField,
|
|
31
|
+
ProtectedField,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__version__ = "0.1.0"
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
# Base
|
|
38
|
+
"CobraObject",
|
|
39
|
+
|
|
40
|
+
# Decorators
|
|
41
|
+
"private",
|
|
42
|
+
"protected",
|
|
43
|
+
"public",
|
|
44
|
+
"final",
|
|
45
|
+
"override",
|
|
46
|
+
|
|
47
|
+
# Fields
|
|
48
|
+
"PrivateField",
|
|
49
|
+
"ProtectedField",
|
|
50
|
+
|
|
51
|
+
# Exceptions
|
|
52
|
+
"CobraError",
|
|
53
|
+
"PrivateAccessError",
|
|
54
|
+
"ProtectedAccessError",
|
|
55
|
+
"FinalMethodError",
|
|
56
|
+
"OverrideError",
|
|
57
|
+
"CobraConfigurationError",
|
|
58
|
+
]
|
cobra/base.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cobra.object
|
|
3
|
+
|
|
4
|
+
Base object for all COBRA-enabled classes.
|
|
5
|
+
|
|
6
|
+
Version: 0.1.0
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CobraObject:
|
|
11
|
+
"""
|
|
12
|
+
Base class for all COBRA objects.
|
|
13
|
+
|
|
14
|
+
Future versions will provide:
|
|
15
|
+
|
|
16
|
+
- Runtime access control
|
|
17
|
+
- Field interception
|
|
18
|
+
- Contract validation
|
|
19
|
+
- Reflection utilities
|
|
20
|
+
- Metadata support
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __repr__(self):
|
|
24
|
+
return f"<{self.__class__.__name__} at {hex(id(self))}>"
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return self.__repr__()
|
|
28
|
+
|
|
29
|
+
# ------------------------------------------------------------------
|
|
30
|
+
# Reserved for COBRA v0.2+
|
|
31
|
+
# ------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
def __getattribute__(self, name):
|
|
34
|
+
"""
|
|
35
|
+
Reserved for future runtime access interception.
|
|
36
|
+
|
|
37
|
+
In v0.2 this will become the central point for
|
|
38
|
+
field-level encapsulation.
|
|
39
|
+
"""
|
|
40
|
+
return super().__getattribute__(name)
|
|
41
|
+
|
|
42
|
+
def __setattr__(self, name, value):
|
|
43
|
+
"""
|
|
44
|
+
Reserved for future runtime write interception.
|
|
45
|
+
"""
|
|
46
|
+
super().__setattr__(name, value)
|
|
47
|
+
|
|
48
|
+
def __delattr__(self, name):
|
|
49
|
+
"""
|
|
50
|
+
Reserved for future runtime delete interception.
|
|
51
|
+
"""
|
|
52
|
+
super().__delattr__(name)
|
cobra/decorators.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cobra.decorators
|
|
3
|
+
|
|
4
|
+
Decorators for enforcing optional OOP access modifiers.
|
|
5
|
+
|
|
6
|
+
Version: 0.1.0
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from functools import wraps
|
|
10
|
+
|
|
11
|
+
from .exceptions import PrivateAccessError
|
|
12
|
+
from .utils import is_private_access_allowed
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def private(func):
|
|
16
|
+
"""
|
|
17
|
+
Marks a method as private.
|
|
18
|
+
|
|
19
|
+
A private method may only be called from within
|
|
20
|
+
the declaring class.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
class Person:
|
|
24
|
+
|
|
25
|
+
@private
|
|
26
|
+
def secret(self):
|
|
27
|
+
...
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@wraps(func)
|
|
31
|
+
def wrapper(*args, **kwargs):
|
|
32
|
+
if not is_private_access_allowed(func, args):
|
|
33
|
+
raise PrivateAccessError(
|
|
34
|
+
f"Private method '{func.__qualname__}' cannot be accessed from outside its class."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return func(*args, **kwargs)
|
|
38
|
+
|
|
39
|
+
return wrapper
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def protected(func):
|
|
43
|
+
raise NotImplementedError(
|
|
44
|
+
"@protected will be implemented in COBRA v0.2"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def public(func):
|
|
49
|
+
return func
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def final(func):
|
|
53
|
+
raise NotImplementedError(
|
|
54
|
+
"@final will be implemented in COBRA v0.2"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def override(func):
|
|
59
|
+
raise NotImplementedError(
|
|
60
|
+
"@override will be implemented in COBRA v0.2"
|
|
61
|
+
)
|
cobra/exceptions.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cobra.exceptions
|
|
3
|
+
|
|
4
|
+
Custom exceptions used throughout the COBRA framework.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CobraError(Exception):
|
|
9
|
+
"""
|
|
10
|
+
Base exception for all COBRA-related errors.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PrivateAccessError(CobraError):
|
|
17
|
+
"""
|
|
18
|
+
Raised when a private method is accessed
|
|
19
|
+
from outside its declaring class.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ProtectedAccessError(CobraError):
|
|
26
|
+
"""
|
|
27
|
+
Raised when a protected member is accessed
|
|
28
|
+
from an unauthorized context.
|
|
29
|
+
|
|
30
|
+
(Reserved for COBRA v0.2)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class FinalMethodError(CobraError):
|
|
37
|
+
"""
|
|
38
|
+
Raised when attempting to override
|
|
39
|
+
a final method.
|
|
40
|
+
|
|
41
|
+
(Reserved for COBRA v0.2)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class OverrideError(CobraError):
|
|
48
|
+
"""
|
|
49
|
+
Raised when an @override method does not
|
|
50
|
+
override any method in the parent class.
|
|
51
|
+
|
|
52
|
+
(Reserved for COBRA v0.2)
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class CobraConfigurationError(CobraError):
|
|
59
|
+
"""
|
|
60
|
+
Raised when COBRA is used incorrectly,
|
|
61
|
+
such as applying decorators to unsupported
|
|
62
|
+
objects.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
pass
|
cobra/fields.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cobra.fields
|
|
3
|
+
|
|
4
|
+
Descriptor implementations for COBRA.
|
|
5
|
+
|
|
6
|
+
Version: 0.1.0
|
|
7
|
+
|
|
8
|
+
NOTE:
|
|
9
|
+
Field-level encapsulation is planned for COBRA v0.2.
|
|
10
|
+
This file provides the initial structure only.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .exceptions import PrivateAccessError, ProtectedAccessError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PrivateField:
|
|
17
|
+
"""
|
|
18
|
+
Descriptor representing a private field.
|
|
19
|
+
|
|
20
|
+
Access control will be enforced in COBRA v0.2.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, default=None):
|
|
24
|
+
self.default = default
|
|
25
|
+
self.storage_name = None
|
|
26
|
+
|
|
27
|
+
def __set_name__(self, owner, name):
|
|
28
|
+
self.storage_name = f"__cobra_private_{name}"
|
|
29
|
+
|
|
30
|
+
def __get__(self, instance, owner):
|
|
31
|
+
if instance is None:
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
# TODO:
|
|
35
|
+
# Enforce private access using caller inspection.
|
|
36
|
+
return getattr(instance, self.storage_name, self.default)
|
|
37
|
+
|
|
38
|
+
def __set__(self, instance, value):
|
|
39
|
+
# TODO:
|
|
40
|
+
# Enforce private write access.
|
|
41
|
+
setattr(instance, self.storage_name, value)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ProtectedField:
|
|
45
|
+
"""
|
|
46
|
+
Descriptor representing a protected field.
|
|
47
|
+
|
|
48
|
+
Access control will be enforced in COBRA v0.2.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, default=None):
|
|
52
|
+
self.default = default
|
|
53
|
+
self.storage_name = None
|
|
54
|
+
|
|
55
|
+
def __set_name__(self, owner, name):
|
|
56
|
+
self.storage_name = f"__cobra_protected_{name}"
|
|
57
|
+
|
|
58
|
+
def __get__(self, instance, owner):
|
|
59
|
+
if instance is None:
|
|
60
|
+
return self
|
|
61
|
+
|
|
62
|
+
# TODO:
|
|
63
|
+
# Enforce protected access.
|
|
64
|
+
return getattr(instance, self.storage_name, self.default)
|
|
65
|
+
|
|
66
|
+
def __set__(self, instance, value):
|
|
67
|
+
# TODO:
|
|
68
|
+
# Enforce protected write access.
|
|
69
|
+
setattr(instance, self.storage_name, value)
|
cobra/utils.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cobra.utils
|
|
3
|
+
|
|
4
|
+
Utility functions used by COBRA decorators.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import inspect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def is_private_access_allowed(func, args):
|
|
11
|
+
"""
|
|
12
|
+
Returns True if a private method is being called
|
|
13
|
+
from within its declaring class.
|
|
14
|
+
|
|
15
|
+
NOTE:
|
|
16
|
+
This is a Proof-of-Concept implementation for COBRA v0.1.
|
|
17
|
+
It is not intended to be security hardened.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# Private methods should always be instance methods.
|
|
21
|
+
if not args:
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
instance = args[0]
|
|
25
|
+
owner_class = instance.__class__
|
|
26
|
+
|
|
27
|
+
# The caller is two frames above:
|
|
28
|
+
#
|
|
29
|
+
# user_code()
|
|
30
|
+
# -> wrapper()
|
|
31
|
+
# -> is_private_access_allowed()
|
|
32
|
+
#
|
|
33
|
+
frame = inspect.currentframe()
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
wrapper_frame = frame.f_back
|
|
37
|
+
caller_frame = wrapper_frame.f_back
|
|
38
|
+
|
|
39
|
+
if caller_frame is None:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
caller_self = caller_frame.f_locals.get("self")
|
|
43
|
+
|
|
44
|
+
# No 'self' means the caller is outside any instance method.
|
|
45
|
+
if caller_self is None:
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
# Allow calls only from the same instance type.
|
|
49
|
+
return isinstance(caller_self, owner_class)
|
|
50
|
+
|
|
51
|
+
finally:
|
|
52
|
+
# Prevent reference cycles.
|
|
53
|
+
del frame
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cobra-oop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Comprehensive Object-Based Runtime Architecture
|
|
5
|
+
Author: Vishnu Swaroop
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: python,oop,decorators,encapsulation,runtime
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# COBRA 🐍
|
|
16
|
+
|
|
17
|
+
> **Comprehensive Object-Based Runtime Architecture**
|
|
18
|
+
|
|
19
|
+
**COBRA** is an experimental Python library that introduces **optional runtime-enforced object-oriented programming concepts** while remaining fully compatible with standard Python.
|
|
20
|
+
|
|
21
|
+
Python follows the philosophy of *"We're all consenting adults here."* COBRA embraces that philosophy while providing developers with the option to enforce stronger object-oriented constraints when building large or enterprise-grade applications.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Why COBRA?
|
|
26
|
+
|
|
27
|
+
Python intentionally relies on conventions instead of strict access modifiers.
|
|
28
|
+
|
|
29
|
+
For example:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
class BankAccount:
|
|
33
|
+
def __reset_pin(self):
|
|
34
|
+
...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Although name mangling discourages accidental access, private members are still accessible when explicitly referenced.
|
|
38
|
+
|
|
39
|
+
COBRA explores an alternative approach by introducing optional runtime validation for concepts such as:
|
|
40
|
+
|
|
41
|
+
* Private methods
|
|
42
|
+
* Protected methods
|
|
43
|
+
* Private fields
|
|
44
|
+
* Final methods
|
|
45
|
+
* Runtime contracts
|
|
46
|
+
* Interface validation
|
|
47
|
+
|
|
48
|
+
The goal is **not to replace Python**, but to provide an optional layer of additional runtime guarantees.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
### Current (v0.1)
|
|
55
|
+
|
|
56
|
+
* ✅ `@private`
|
|
57
|
+
* ✅ Runtime access validation
|
|
58
|
+
* ✅ Custom exception hierarchy
|
|
59
|
+
* ✅ Unit tests
|
|
60
|
+
* ✅ Extensible architecture
|
|
61
|
+
|
|
62
|
+
### Planned
|
|
63
|
+
|
|
64
|
+
* `@protected`
|
|
65
|
+
* `PrivateField`
|
|
66
|
+
* `ProtectedField`
|
|
67
|
+
* `@final`
|
|
68
|
+
* `@override`
|
|
69
|
+
* Runtime contracts
|
|
70
|
+
* Interface support
|
|
71
|
+
* Performance optimisations
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install cobra-oop
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For development:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install -e .
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Quick Example
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from cobra import CobraObject, private
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class BankAccount(CobraObject):
|
|
96
|
+
|
|
97
|
+
@private
|
|
98
|
+
def reset_pin(self):
|
|
99
|
+
print("PIN reset")
|
|
100
|
+
|
|
101
|
+
def change_pin(self):
|
|
102
|
+
self.reset_pin()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
account = BankAccount()
|
|
106
|
+
|
|
107
|
+
account.change_pin() # ✅ Allowed
|
|
108
|
+
account.reset_pin() # ❌ Raises PrivateAccessError
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Project Structure
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
cobra/
|
|
117
|
+
├── decorators.py
|
|
118
|
+
├── fields.py
|
|
119
|
+
├── base.py
|
|
120
|
+
├── exceptions.py
|
|
121
|
+
├── utils.py
|
|
122
|
+
└── __init__.py
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Roadmap
|
|
128
|
+
|
|
129
|
+
The development roadmap can be found in:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
docs/roadmap.md
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Architecture decisions are documented under:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
docs/adr/
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Philosophy
|
|
144
|
+
|
|
145
|
+
COBRA is designed around a few simple principles:
|
|
146
|
+
|
|
147
|
+
* Keep Pythonic syntax.
|
|
148
|
+
* Make strictness optional.
|
|
149
|
+
* Prefer explicit behaviour over hidden magic.
|
|
150
|
+
* Build small, testable components.
|
|
151
|
+
* Learn by exploring Python internals.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Contributing
|
|
156
|
+
|
|
157
|
+
Contributions, suggestions, and discussions are always welcome.
|
|
158
|
+
|
|
159
|
+
If you discover an issue or have an idea for improving COBRA, feel free to open an issue or submit a pull request.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
This project is licensed under the MIT License.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
> *"Python trusts developers. COBRA helps developers trust each other."* 🐍
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
cobra/__init__.py,sha256=rM21gZXUBtIg6lFoNzAsCDmBQwOSN13TK5uRJMGE5W0,892
|
|
2
|
+
cobra/base.py,sha256=-zGZxktvwOtOS6p5Jt74BImFCDKXgTrTJzXF0z-nACI,1212
|
|
3
|
+
cobra/decorators.py,sha256=vkQgXPjwx4o2GEkFPGaFUnHipYVoA5i3-9BafpTKL_g,1155
|
|
4
|
+
cobra/exceptions.py,sha256=ntgxcsOwDgXJ5CBX3GsUj_dJt0z1yl9ajSp0Wp0Tb74,1025
|
|
5
|
+
cobra/fields.py,sha256=nmOLNSczfal3TLbA-VU1LDaDnM1czuaDcOKMIRyUJgQ,1670
|
|
6
|
+
cobra/utils.py,sha256=ExAat3dPXLozEj6z82TUQLXoBj0OD7yP31kCTFmj4po,1188
|
|
7
|
+
cobra_oop-0.1.0.dist-info/licenses/LICENSE,sha256=VTR0d33ThYBTk2TpAuM7koboaTaHt0wu7aGMLOOUe5w,1070
|
|
8
|
+
cobra_oop-0.1.0.dist-info/METADATA,sha256=4CrPC2KcnYJd0aBznAJNKGeuDRSIpGEwOHiXbjk52ic,3255
|
|
9
|
+
cobra_oop-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
10
|
+
cobra_oop-0.1.0.dist-info/top_level.txt,sha256=LeT4BKKqEqFNqc-EGNWRSpdtIvqG4eLt-Qn3Rf1EmG8,6
|
|
11
|
+
cobra_oop-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vishnu Swaroop
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cobra
|