aimodelshare 0.1.59__py3-none-any.whl → 0.1.60__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.
Potentially problematic release.
This version of aimodelshare might be problematic. Click here for more details.
- aimodelshare/aws.py +4 -4
- aimodelshare/generatemodelapi.py +1 -1
- aimodelshare/model.py +1 -1
- aimodelshare/modeluser.py +67 -1
- aimodelshare/moral_compass/README.md +41 -0
- aimodelshare/moral_compass/_version.py +1 -1
- aimodelshare/moral_compass/api_client.py +49 -1
- {aimodelshare-0.1.59.dist-info → aimodelshare-0.1.60.dist-info}/METADATA +1 -1
- {aimodelshare-0.1.59.dist-info → aimodelshare-0.1.60.dist-info}/RECORD +12 -12
- {aimodelshare-0.1.59.dist-info → aimodelshare-0.1.60.dist-info}/WHEEL +0 -0
- {aimodelshare-0.1.59.dist-info → aimodelshare-0.1.60.dist-info}/licenses/LICENSE +0 -0
- {aimodelshare-0.1.59.dist-info → aimodelshare-0.1.60.dist-info}/top_level.txt +0 -0
aimodelshare/aws.py
CHANGED
|
@@ -10,7 +10,7 @@ def set_credentials(credential_file=None, type="submit_model", apiurl="apiurl",
|
|
|
10
10
|
import os
|
|
11
11
|
import getpass
|
|
12
12
|
from aimodelshare.aws import get_aws_token
|
|
13
|
-
from aimodelshare.modeluser import get_jwt_token,
|
|
13
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
14
14
|
if all([credential_file==None, type=="submit_model"]):
|
|
15
15
|
set_credentials_public(type="submit_model", apiurl=apiurl)
|
|
16
16
|
os.environ["AWS_TOKEN"]=get_aws_token()
|
|
@@ -131,7 +131,7 @@ def set_credentials(credential_file=None, type="submit_model", apiurl="apiurl",
|
|
|
131
131
|
# Set Environment Variables for deploy models
|
|
132
132
|
if type == "deploy_model":
|
|
133
133
|
get_jwt_token(os.environ.get("username"), os.environ.get("password"))
|
|
134
|
-
|
|
134
|
+
setup_bucket_only() # Use new function that doesn't create IAM users
|
|
135
135
|
|
|
136
136
|
if not flag:
|
|
137
137
|
print("Error: apiurl or type not found in"+str(credential_file)+". Please correct entries and resubmit.")
|
|
@@ -147,7 +147,7 @@ def set_credentials_public(credential_file=None, type="submit_model", apiurl="ap
|
|
|
147
147
|
import os
|
|
148
148
|
import getpass
|
|
149
149
|
from aimodelshare.aws import get_aws_token
|
|
150
|
-
from aimodelshare.modeluser import get_jwt_token,
|
|
150
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
151
151
|
|
|
152
152
|
##TODO: Require that "type" is provided, to ensure correct env vars get loaded
|
|
153
153
|
flag = False
|
|
@@ -211,7 +211,7 @@ def set_credentials_public_aimscloud(credential_file=None, type="deploy_model",
|
|
|
211
211
|
import os
|
|
212
212
|
import getpass
|
|
213
213
|
from aimodelshare.aws import get_aws_token
|
|
214
|
-
from aimodelshare.modeluser import get_jwt_token,
|
|
214
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
215
215
|
|
|
216
216
|
##TODO: Require that "type" is provided, to ensure correct env vars get loaded
|
|
217
217
|
flag = False
|
aimodelshare/generatemodelapi.py
CHANGED
|
@@ -23,7 +23,7 @@ from aimodelshare.aws import get_s3_iam_client, run_function_on_lambda, get_toke
|
|
|
23
23
|
from aimodelshare.bucketpolicy import _custom_upload_policy
|
|
24
24
|
from aimodelshare.exceptions import AuthorizationError, AWSAccessError, AWSUploadError
|
|
25
25
|
from aimodelshare.api import get_api_json
|
|
26
|
-
from aimodelshare.modeluser import
|
|
26
|
+
from aimodelshare.modeluser import decode_token_unverified
|
|
27
27
|
from aimodelshare.preprocessormodules import upload_preprocessor
|
|
28
28
|
from aimodelshare.model import _get_predictionmodel_key, _extract_model_metadata
|
|
29
29
|
from aimodelshare.data_sharing.share_data import share_data_codebuild
|
aimodelshare/model.py
CHANGED
|
@@ -918,7 +918,7 @@ def submit_model(
|
|
|
918
918
|
|
|
919
919
|
import os
|
|
920
920
|
from aimodelshare.aws import get_aws_token
|
|
921
|
-
from aimodelshare.modeluser import get_jwt_token
|
|
921
|
+
from aimodelshare.modeluser import get_jwt_token
|
|
922
922
|
import ast
|
|
923
923
|
|
|
924
924
|
# Confirm that creds are loaded, raise error if not
|
aimodelshare/modeluser.py
CHANGED
|
@@ -55,8 +55,73 @@ def get_jwt_token(username, password):
|
|
|
55
55
|
|
|
56
56
|
return
|
|
57
57
|
|
|
58
|
-
def
|
|
58
|
+
def setup_bucket_only():
|
|
59
|
+
"""
|
|
60
|
+
Set up the S3 bucket for aimodelshare without creating new IAM users.
|
|
61
|
+
|
|
62
|
+
Uses the provided AWS credentials to create or access the bucket.
|
|
63
|
+
This avoids creating a new IAM user every time credentials are set.
|
|
64
|
+
"""
|
|
65
|
+
from aimodelshare.aws import get_s3_iam_client
|
|
59
66
|
|
|
67
|
+
s3, iam, region = get_s3_iam_client(os.environ.get("AWS_ACCESS_KEY_ID_AIMS"),
|
|
68
|
+
os.environ.get("AWS_SECRET_ACCESS_KEY_AIMS"),
|
|
69
|
+
os.environ.get("AWS_REGION_AIMS"))
|
|
70
|
+
|
|
71
|
+
user_session = boto3.session.Session(aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID_AIMS"),
|
|
72
|
+
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY_AIMS"),
|
|
73
|
+
region_name= os.environ.get("AWS_REGION_AIMS"))
|
|
74
|
+
|
|
75
|
+
account_number = user_session.client(
|
|
76
|
+
'sts').get_caller_identity().get('Account')
|
|
77
|
+
|
|
78
|
+
# Remove special characters from username
|
|
79
|
+
username_clean = re.sub('[^A-Za-z0-9-]+', '', os.environ.get("username"))
|
|
80
|
+
bucket_name = 'aimodelshare' + username_clean.lower() + str(account_number) + region.replace('-', '')
|
|
81
|
+
|
|
82
|
+
region = os.environ.get("AWS_REGION_AIMS")
|
|
83
|
+
s3_client = s3['client']
|
|
84
|
+
|
|
85
|
+
# Create bucket if it doesn't exist
|
|
86
|
+
try:
|
|
87
|
+
response = s3_client.head_bucket(Bucket=bucket_name)
|
|
88
|
+
except:
|
|
89
|
+
if region == "us-east-1":
|
|
90
|
+
response = s3_client.create_bucket(
|
|
91
|
+
ACL="private",
|
|
92
|
+
Bucket=bucket_name
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
location = {'LocationConstraint': region}
|
|
96
|
+
response = s3_client.create_bucket(
|
|
97
|
+
ACL="private",
|
|
98
|
+
Bucket=bucket_name,
|
|
99
|
+
CreateBucketConfiguration=location
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Set the bucket name in environment for use by other functions
|
|
103
|
+
os.environ["BUCKET_NAME"] = bucket_name
|
|
104
|
+
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def create_user_getkeyandpassword():
|
|
109
|
+
"""
|
|
110
|
+
DEPRECATED: This function creates a new IAM user every time it's called.
|
|
111
|
+
|
|
112
|
+
Use setup_bucket_only() instead, which uses the provided AWS credentials
|
|
113
|
+
without creating new IAM users and policies.
|
|
114
|
+
|
|
115
|
+
This function is kept for backward compatibility but should not be used.
|
|
116
|
+
"""
|
|
117
|
+
import warnings
|
|
118
|
+
warnings.warn(
|
|
119
|
+
"create_user_getkeyandpassword() is deprecated and creates unnecessary IAM users. "
|
|
120
|
+
"Use setup_bucket_only() instead.",
|
|
121
|
+
DeprecationWarning,
|
|
122
|
+
stacklevel=2
|
|
123
|
+
)
|
|
124
|
+
|
|
60
125
|
from aimodelshare.bucketpolicy import _custom_s3_policy
|
|
61
126
|
from aimodelshare.tools import form_timestamp
|
|
62
127
|
from aimodelshare.aws import get_s3_iam_client
|
|
@@ -145,5 +210,6 @@ def create_user_getkeyandpassword():
|
|
|
145
210
|
__all__ = [
|
|
146
211
|
get_jwt_token,
|
|
147
212
|
create_user_getkeyandpassword,
|
|
213
|
+
setup_bucket_only,
|
|
148
214
|
decode_token_unverified,
|
|
149
215
|
]
|
|
@@ -91,6 +91,47 @@ client = MoralcompassApiClient(auth_token="your.jwt.token")
|
|
|
91
91
|
client = MoralcompassApiClient() # Uses JWT_AUTHORIZATION_TOKEN or AWS_TOKEN
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
### Automatic Token Acquisition
|
|
95
|
+
|
|
96
|
+
If no JWT token is found in environment variables, the client will attempt to auto-generate one using username and password credentials. This provides seamless integration when users have already configured credentials via `configure_credentials()`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Set credentials for automatic JWT generation
|
|
100
|
+
export AIMODELSHARE_USERNAME="your-username"
|
|
101
|
+
export AIMODELSHARE_PASSWORD="your-password"
|
|
102
|
+
|
|
103
|
+
# Alternative variable names also supported
|
|
104
|
+
export username="your-username"
|
|
105
|
+
export password="your-password"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from aimodelshare.moral_compass import MoralcompassApiClient
|
|
110
|
+
from aimodelshare.modeluser import get_jwt_token
|
|
111
|
+
import os
|
|
112
|
+
|
|
113
|
+
# Method 1: Let the client auto-generate (recommended)
|
|
114
|
+
# Client will automatically use AIMODELSHARE_USERNAME/AIMODELSHARE_PASSWORD
|
|
115
|
+
client = MoralcompassApiClient()
|
|
116
|
+
|
|
117
|
+
# Method 2: Explicitly generate and set JWT token
|
|
118
|
+
if not os.getenv('JWT_AUTHORIZATION_TOKEN'):
|
|
119
|
+
username = os.getenv('AIMODELSHARE_USERNAME')
|
|
120
|
+
password = os.getenv('AIMODELSHARE_PASSWORD')
|
|
121
|
+
if username and password:
|
|
122
|
+
get_jwt_token(username, password) # Sets JWT_AUTHORIZATION_TOKEN
|
|
123
|
+
# Now JWT_AUTHORIZATION_TOKEN is available for subsequent API calls
|
|
124
|
+
|
|
125
|
+
client = MoralcompassApiClient()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The auto-generation process:
|
|
129
|
+
1. Checks for existing JWT_AUTHORIZATION_TOKEN (skips if found)
|
|
130
|
+
2. Looks for AIMODELSHARE_USERNAME/AIMODELSHARE_PASSWORD or username/password
|
|
131
|
+
3. Calls `get_jwt_token()` to generate and set JWT_AUTHORIZATION_TOKEN
|
|
132
|
+
4. Uses the generated token for API authentication
|
|
133
|
+
5. Logs success/failure for debugging
|
|
134
|
+
|
|
94
135
|
### Table Ownership
|
|
95
136
|
|
|
96
137
|
When authentication is enabled, tables have ownership metadata:
|
|
@@ -96,6 +96,11 @@ class MoralcompassApiClient:
|
|
|
96
96
|
self.api_base_url = (api_base_url or get_api_base_url()).rstrip("/")
|
|
97
97
|
self.timeout = timeout
|
|
98
98
|
self.auth_token = auth_token or self._get_auth_token_from_env()
|
|
99
|
+
|
|
100
|
+
# Auto-generate JWT if no token found but credentials available
|
|
101
|
+
if not self.auth_token:
|
|
102
|
+
self._auto_generate_jwt_if_possible()
|
|
103
|
+
|
|
99
104
|
self.session = self._create_session()
|
|
100
105
|
logger.info(f"MoralcompassApiClient initialized with base URL: {self.api_base_url}")
|
|
101
106
|
|
|
@@ -115,6 +120,42 @@ class MoralcompassApiClient:
|
|
|
115
120
|
# Fallback to direct environment variable access if auth module not available
|
|
116
121
|
return os.getenv('JWT_AUTHORIZATION_TOKEN') or os.getenv('AWS_TOKEN')
|
|
117
122
|
|
|
123
|
+
def _auto_generate_jwt_if_possible(self) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Attempt to auto-generate a JWT token if credentials are available.
|
|
126
|
+
|
|
127
|
+
Checks for username/password environment variables and uses them to generate
|
|
128
|
+
a JWT token via aimodelshare.modeluser.get_jwt_token if possible.
|
|
129
|
+
|
|
130
|
+
Sets self.auth_token and exports JWT_AUTHORIZATION_TOKEN if successful.
|
|
131
|
+
"""
|
|
132
|
+
# Check for username/password environment variables
|
|
133
|
+
username = os.getenv('AIMODELSHARE_USERNAME') or os.getenv('username')
|
|
134
|
+
password = os.getenv('AIMODELSHARE_PASSWORD') or os.getenv('password')
|
|
135
|
+
|
|
136
|
+
if not (username and password):
|
|
137
|
+
logger.debug("Auto JWT generation skipped: No username/password credentials found in environment")
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
from aimodelshare.modeluser import get_jwt_token
|
|
142
|
+
|
|
143
|
+
# Generate JWT token
|
|
144
|
+
logger.debug(f"Attempting to auto-generate JWT token for user: {username[:3]}***")
|
|
145
|
+
get_jwt_token(username, password)
|
|
146
|
+
|
|
147
|
+
# get_jwt_token sets JWT_AUTHORIZATION_TOKEN in environment, retrieve it
|
|
148
|
+
token = os.getenv('JWT_AUTHORIZATION_TOKEN')
|
|
149
|
+
if token:
|
|
150
|
+
self.auth_token = token
|
|
151
|
+
logger.info(f"Auto-generated JWT token for moral_compass client. Token: {token[:10]}...")
|
|
152
|
+
else:
|
|
153
|
+
logger.debug("JWT token generation completed but JWT_AUTHORIZATION_TOKEN not found in environment")
|
|
154
|
+
|
|
155
|
+
except Exception as e:
|
|
156
|
+
logger.debug(f"Auto JWT generation failed: {e}")
|
|
157
|
+
# Continue without token - let the actual API calls handle authorization errors
|
|
158
|
+
|
|
118
159
|
def _create_session(self) -> requests.Session:
|
|
119
160
|
"""
|
|
120
161
|
Create a requests session with retry configuration.
|
|
@@ -172,7 +213,14 @@ class MoralcompassApiClient:
|
|
|
172
213
|
)
|
|
173
214
|
|
|
174
215
|
# Handle specific error codes
|
|
175
|
-
if response.status_code ==
|
|
216
|
+
if response.status_code == 401:
|
|
217
|
+
auth_msg = "Authentication failed (401 Unauthorized)"
|
|
218
|
+
if not self.auth_token:
|
|
219
|
+
auth_msg += ". No authentication token provided. Set JWT_AUTHORIZATION_TOKEN environment variable or set AIMODELSHARE_USERNAME/AIMODELSHARE_PASSWORD for automatic JWT generation."
|
|
220
|
+
else:
|
|
221
|
+
auth_msg += f". Token present but invalid or expired. Token: {self.auth_token[:10]}..."
|
|
222
|
+
raise ApiClientError(f"{auth_msg} | URL: {response.url} | Response: {response.text}")
|
|
223
|
+
elif response.status_code == 404:
|
|
176
224
|
raise NotFoundError(f"Resource not found: {path} | body={response.text}")
|
|
177
225
|
elif 500 <= response.status_code < 600:
|
|
178
226
|
raise ServerError(f"Server error {response.status_code}: {response.text}")
|
|
@@ -3,7 +3,7 @@ aimodelshare/__init__.py,sha256=csP3KFDIvloTtRqqGh7Jg1eo0Q6-V63VQbgYR2zzWZs,3228
|
|
|
3
3
|
aimodelshare/aimsonnx.py,sha256=NCjRd535kTfJ6zSEa2o9QpC-TqHPIiDNuS0yHcAQzx8,77178
|
|
4
4
|
aimodelshare/api.py,sha256=3AuTS88M-6zXye3eCjjaAnHpdvLjHHdYMyPZJm9O0Cc,35107
|
|
5
5
|
aimodelshare/auth.py,sha256=7FatqYMDF3x2u9GRuNm-2lvMMLKO1AHtWRxzu36ZVqE,4774
|
|
6
|
-
aimodelshare/aws.py,sha256=
|
|
6
|
+
aimodelshare/aws.py,sha256=GSFw1Flc-hIyAk3a_0CtlKTOlhUBSeMF0tcRIweOHbI,15234
|
|
7
7
|
aimodelshare/aws_client.py,sha256=Ce19iwf69BwpuyyJlVN8z1da3c5jf93svsTgx1OWhaA,6784
|
|
8
8
|
aimodelshare/base_image.py,sha256=itaQmX_q5GmgQrL3VNCBJpDGhl4PGA-nLTCbuyNDCCc,4825
|
|
9
9
|
aimodelshare/bucketpolicy.py,sha256=KLyl-BLBiFdTYzCK7tJV8NBJHBKWRlF3_msSTGwgaQQ,3055
|
|
@@ -12,10 +12,10 @@ aimodelshare/containerization.py,sha256=Sa9GWxmz1qoDZ3lUQjFa1ctQUSs666I7-Yf0YU3W
|
|
|
12
12
|
aimodelshare/custom_eval_metrics.py,sha256=NghFslmLDyvIkZ27yZhFIItLbzHnNb0bJ2ZO7cqkucw,3170
|
|
13
13
|
aimodelshare/deploy_custom_lambda.py,sha256=HFxxIYI2JrZwPrjqKgFkj6KaCeRBOn6tf9e2fqBUl2U,11045
|
|
14
14
|
aimodelshare/exceptions.py,sha256=gfrwQ7LHNyjgUNHM4X_LNZ7JhKwZv9qWN3DhBaB-f-k,318
|
|
15
|
-
aimodelshare/generatemodelapi.py,sha256=
|
|
15
|
+
aimodelshare/generatemodelapi.py,sha256=lfJQs93gu_WYrUPmbXrb0Whe3cABLtvA5cXpqq2gs8A,59701
|
|
16
16
|
aimodelshare/leaderboard.py,sha256=xtKJcNCsZjy2IoK1fUTAFyM_I-eLCMS1WJRfwgsT5AA,5216
|
|
17
|
-
aimodelshare/model.py,sha256=
|
|
18
|
-
aimodelshare/modeluser.py,sha256=
|
|
17
|
+
aimodelshare/model.py,sha256=_W7479wJxzsguDBKhmaNZyAtuSHiNI_fF6EZAOtbL8w,62311
|
|
18
|
+
aimodelshare/modeluser.py,sha256=uZJjwaT7zHBEcfttl6JYxvDdabKl36YdgvSjRa-gF8E,7512
|
|
19
19
|
aimodelshare/playground.py,sha256=jOMls-mv_A8W8AOM8ZCpSci63UauciMxPH5VwHclLN0,89273
|
|
20
20
|
aimodelshare/postprocessormodules.py,sha256=L87fM2mywlInOrgaMETi-7zdHBGbIMRcrXKttQthyQ4,4992
|
|
21
21
|
aimodelshare/preprocessormodules.py,sha256=48HIur55nytD0FdhW1u1wWSAiaIW4uof0cJP1Yoq0T4,13183
|
|
@@ -112,10 +112,10 @@ aimodelshare/main/eval_lambda.txt,sha256=r3GqJodO5QG6jeK4xWUzLrXM9K7XLXeUJouhz6e
|
|
|
112
112
|
aimodelshare/main/eval_regression.txt,sha256=iQeE9mbOkg-BDF9TnoQmglo86jBJitJQCvaf1eELzrs,3111
|
|
113
113
|
aimodelshare/main/lambda_function.txt,sha256=-XkuD2YUOWNryNT7rBPjlts588UAeE949TUqeVGCRlQ,150
|
|
114
114
|
aimodelshare/main/nst.txt,sha256=8kTsR18kDEcaQbv6091XDq1tRiqqFxdqfCteslR_udk,4941
|
|
115
|
-
aimodelshare/moral_compass/README.md,sha256=
|
|
115
|
+
aimodelshare/moral_compass/README.md,sha256=2wTCI0s43Tm9WXRIJjtj6h-FFHsdHhzx-Aimy_UupBY,11888
|
|
116
116
|
aimodelshare/moral_compass/__init__.py,sha256=CRUuQLeccumeFDl4RZDxFNFZlUw73W0wA5n7adYhgew,1708
|
|
117
|
-
aimodelshare/moral_compass/_version.py,sha256=
|
|
118
|
-
aimodelshare/moral_compass/api_client.py,sha256=
|
|
117
|
+
aimodelshare/moral_compass/_version.py,sha256=GhviEK9nfN1o9XunS8V4jXqgMmcB-Vpp2VCYWplLzqE,80
|
|
118
|
+
aimodelshare/moral_compass/api_client.py,sha256=3WVWBuuEJ9x0R6raUu6TKZPv2swgVxCDwKXKg8Esq24,22393
|
|
119
119
|
aimodelshare/moral_compass/challenge.py,sha256=p--uqP30tPQnVcOPs4LEJFaXlqTRL9Zb7SVkEvggl2U,12971
|
|
120
120
|
aimodelshare/moral_compass/config.py,sha256=8HsoTreAAdXaWOdg30B1IJXwIGMBNEz7hqgNZpAFUhI,6119
|
|
121
121
|
aimodelshare/placeholders/model.onnx,sha256=i04ndsRw5VBTOpIH-LHqTjAPHcJZNzyWSSz1zSmukBw,3464
|
|
@@ -149,8 +149,8 @@ aimodelshare/sam/spark-class.txt,sha256=chyJBxDzCzlUKXzVQYTzuJ2PXCTwg8_gd1yfnI-x
|
|
|
149
149
|
aimodelshare/sam/template.txt,sha256=JKSvEOZNaaLalHSx7r9psJg_6LLCb0XLAYi1-jYPu3M,1195
|
|
150
150
|
aimodelshare/utils/__init__.py,sha256=6ieChHjYDsn_gSyeOiLeWW5hWkUfZUucEzSFyBN7xck,1973
|
|
151
151
|
aimodelshare/utils/optional_deps.py,sha256=t0ZcPlaAKEQqBpD-GDbFGg9a-qp2fsqonTVM0dLWNV4,1257
|
|
152
|
-
aimodelshare-0.1.
|
|
153
|
-
aimodelshare-0.1.
|
|
154
|
-
aimodelshare-0.1.
|
|
155
|
-
aimodelshare-0.1.
|
|
156
|
-
aimodelshare-0.1.
|
|
152
|
+
aimodelshare-0.1.60.dist-info/licenses/LICENSE,sha256=XdPthYienQee9LH1duXNGtsj6GUTXPvtf_1MpC8WhL4,115
|
|
153
|
+
aimodelshare-0.1.60.dist-info/METADATA,sha256=63ASeulZNPn9b-bpyy0uwLiEHp92d9ToXOzIAr8j3Uo,8731
|
|
154
|
+
aimodelshare-0.1.60.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
155
|
+
aimodelshare-0.1.60.dist-info/top_level.txt,sha256=d-0DAtZDZsvfauQzUjXHJRKVYfaqMWZXz3WGmmIzE5w,13
|
|
156
|
+
aimodelshare-0.1.60.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|