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 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, create_user_getkeyandpassword
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
- create_user_getkeyandpassword()
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, create_user_getkeyandpassword
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, create_user_getkeyandpassword
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
@@ -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 create_user_getkeyandpassword, decode_token_unverified
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, create_user_getkeyandpassword
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 create_user_getkeyandpassword():
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:
@@ -1,3 +1,3 @@
1
1
  """Version information for aimodelshare.moral_compass"""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.1.1"
@@ -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 == 404:
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}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aimodelshare
3
- Version: 0.1.59
3
+ Version: 0.1.60
4
4
  Summary: Deploy locally saved machine learning models to a live REST API and integrated dashboard.
5
5
  Author-email: Michael Parrott <mikedparrott@modelshare.ai>
6
6
  License:
@@ -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=jn99R9-N77Qac-_eYm-LaCQUPd-RnE7oVULm9rh-3RY,15232
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=fxQ90Fpcz6jCG0vFJ1GweIYjxFT_u92C3qe5ZW-D8A8,59732
15
+ aimodelshare/generatemodelapi.py,sha256=lfJQs93gu_WYrUPmbXrb0Whe3cABLtvA5cXpqq2gs8A,59701
16
16
  aimodelshare/leaderboard.py,sha256=xtKJcNCsZjy2IoK1fUTAFyM_I-eLCMS1WJRfwgsT5AA,5216
17
- aimodelshare/model.py,sha256=HjiETn_IppZ_6x63QSFNViBSDJN_hU44UsSQRzGE4Ow,62342
18
- aimodelshare/modeluser.py,sha256=jyZVRs-31URmKJJMvbM9NBXykiOEsznnYK25LzDo-GU,5006
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=J3D1W1x7KVHLJn5D_Rwhqeaa6CVsywBpU4JmKEtHuAY,10303
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=nGjn9uzc3g2iY_fCxtBI1a6xkZ8xPxgk7PJTt5zKElE,80
118
- aimodelshare/moral_compass/api_client.py,sha256=Z3kXjH7Ryi6QrXbe8I_IL2KqzgWt4EiGIu_YKwa3kFg,19893
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.59.dist-info/licenses/LICENSE,sha256=XdPthYienQee9LH1duXNGtsj6GUTXPvtf_1MpC8WhL4,115
153
- aimodelshare-0.1.59.dist-info/METADATA,sha256=mckigVSwxqMq0P-6QOtcATqvCQ1IU8CztsPLkwx8va8,8731
154
- aimodelshare-0.1.59.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
155
- aimodelshare-0.1.59.dist-info/top_level.txt,sha256=d-0DAtZDZsvfauQzUjXHJRKVYfaqMWZXz3WGmmIzE5w,13
156
- aimodelshare-0.1.59.dist-info/RECORD,,
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,,