def create_content(artifact_sha256, filename): """ Creates PythonPackageContent from artifact. Args: artifact_sha256: validated artifact filename: file name Returns: queryset of the new created content """ artifact = Artifact.objects.get(sha256=artifact_sha256) metadata = get_project_metadata_from_artifact(filename, artifact) data = parse_project_metadata(vars(metadata)) data['packagetype'] = metadata.packagetype data['version'] = metadata.version data['filename'] = filename data['sha256'] = artifact.sha256 @transaction.atomic() def create(): content = PythonPackageContent.objects.create(**data) ContentArtifact.objects.create(artifact=artifact, content=content, relative_path=filename) return content new_content = create() resource = CreatedResource(content_object=new_content) resource.save() return PythonPackageContent.objects.filter(pk=new_content.pk)
def create(self, request): """ Create a new PythonPackageContent from a request. """ try: artifact = self.get_resource(request.data['_artifact'], Artifact) except KeyError: raise serializers.ValidationError( detail={'_artifact': _('This field is required')}) try: filename = request.data['filename'] except KeyError: raise serializers.ValidationError( detail={'filename': _('This field is required')}) # iterate through extensions since splitext does not support things like .tar.gz for ext, packagetype in DIST_EXTENSIONS.items(): if filename.endswith(ext): # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it with tempfile.TemporaryDirectory() as td: temp_path = os.path.join(td, filename) shutil.copy2(artifact.file.path, temp_path) metadata = DIST_TYPES[packagetype](temp_path) metadata.packagetype = packagetype break else: raise serializers.ValidationError( _("Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format( filename)) data = parse_project_metadata(vars(metadata)) data['classifiers'] = [{ 'name': classifier } for classifier in metadata.classifiers] data['packagetype'] = metadata.packagetype data['version'] = metadata.version data['filename'] = filename data['_artifact'] = request.data['_artifact'] serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) serializer.validated_data.pop('_artifact') content = serializer.save() if content.pk: ContentArtifact.objects.create(artifact=artifact, content=content, relative_path=filename) headers = self.get_success_headers(request.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def create(self, request): """ <!-- User-facing documentation, rendered as html--> This endpoint is part of the <a href="workflows/upload.html">Upload workflow.</a> Create a PythonPackageContent here by specifying an uploaded Artifact. `pulp-python` will inspect parse the metadata directly from the file. """ try: artifact = self.get_resource(request.data['_artifact'], Artifact) except KeyError: raise serializers.ValidationError(detail={'_artifact': _('This field is required')}) try: filename = request.data['filename'] except KeyError: raise serializers.ValidationError(detail={'filename': _('This field is required')}) # iterate through extensions since splitext does not support things like .tar.gz for ext, packagetype in DIST_EXTENSIONS.items(): if filename.endswith(ext): # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it with tempfile.TemporaryDirectory() as td: temp_path = os.path.join(td, filename) shutil.copy2(artifact.file.path, temp_path) metadata = DIST_TYPES[packagetype](temp_path) metadata.packagetype = packagetype break else: raise serializers.ValidationError(_( "Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format(filename) ) data = parse_project_metadata(vars(metadata)) data['classifiers'] = [{'name': classifier} for classifier in metadata.classifiers] data['packagetype'] = metadata.packagetype data['version'] = metadata.version data['filename'] = filename data['_artifact'] = request.data['_artifact'] data['_relative_path'] = filename serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() headers = self.get_success_headers(request.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def deferred_validate(self, data): """ Validate the python package data. Args: data (dict): Data to be validated Returns: dict: Data that has been validated """ data = super().deferred_validate(data) try: filename = data["relative_path"] except KeyError: raise serializers.ValidationError( detail={"relative_path": _('This field is required')}) artifact = data["artifact"] try: metadata = get_project_metadata_from_artifact(filename, artifact) except ValueError: raise serializers.ValidationError( _("Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format( filename)) if data.get("sha256") and data["sha256"] != artifact.sha256: raise serializers.ValidationError( detail={ "sha256": _("The uploaded artifact's sha256 checksum does not match the one provided" ) }) sha256 = artifact.sha256 if sha256 and python_models.PythonPackageContent.objects.filter( sha256=sha256).exists(): raise serializers.ValidationError( detail={"sha256": _('This field must be unique')}) _data = parse_project_metadata(vars(metadata)) _data['packagetype'] = metadata.packagetype _data['version'] = metadata.version _data['filename'] = filename _data['sha256'] = sha256 data.update(_data) return data
def one_shot_upload(artifact_pk, filename, repository_pk=None): """ One shot upload for pulp_python Args: artifact_pk: validated artifact filename: file name repository_pk: optional repository to add Content to """ # iterate through extensions since splitext does not support things like .tar.gz for ext, packagetype in DIST_EXTENSIONS.items(): if filename.endswith(ext): # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it with tempfile.TemporaryDirectory() as td: temp_path = os.path.join(td, filename) artifact = Artifact.objects.get(pk=artifact_pk) shutil.copy2(artifact.file.path, temp_path) metadata = DIST_TYPES[packagetype](temp_path) metadata.packagetype = packagetype break else: raise serializers.ValidationError( _("Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format(filename)) data = parse_project_metadata(vars(metadata)) data['classifiers'] = [{ 'name': classifier } for classifier in metadata.classifiers] data['packagetype'] = metadata.packagetype data['version'] = metadata.version data['filename'] = filename data['_relative_path'] = filename new_content = PythonPackageContent.objects.create( filename=filename, packagetype=metadata.packagetype, name=data['classifiers'], version=data['version']) queryset = PythonPackageContent.objects.filter(pk=new_content.pk) if repository_pk: repository = Repository.objects.get(pk=repository_pk) with RepositoryVersion.create(repository) as new_version: new_version.add_content(queryset) resource = CreatedResource(content_object=new_content) resource.save()
def create_content(artifact_sha256, filename): """ Creates PythonPackageContent from artifact. Args: artifact_sha256: validated artifact filename: file name Returns: queryset of the new created content """ # iterate through extensions since splitext does not support things like .tar.gz extensions = list(DIST_EXTENSIONS.keys()) pkg_type_index = [filename.endswith(ext) for ext in extensions].index(True) packagetype = DIST_EXTENSIONS[extensions[pkg_type_index]] # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it artifact = Artifact.objects.get(sha256=artifact_sha256) artifact_file = storage.open(artifact.file.name) with tempfile.NamedTemporaryFile('wb', suffix=filename) as temp_file: shutil.copyfileobj(artifact_file, temp_file) temp_file.flush() metadata = DIST_TYPES[packagetype](temp_file.name) metadata.packagetype = packagetype data = parse_project_metadata(vars(metadata)) data['packagetype'] = metadata.packagetype data['version'] = metadata.version data['filename'] = filename data['sha256'] = artifact.sha256 @transaction.atomic() def create(): content = PythonPackageContent.objects.create(**data) ContentArtifact.objects.create(artifact=artifact, content=content, relative_path=filename) return content new_content = create() resource = CreatedResource(content_object=new_content) resource.save() return PythonPackageContent.objects.filter(pk=new_content.pk)
def deferred_validate(self, data): """ Validate the python package data. Args: data (dict): Data to be validated Returns: dict: Data that has been validated """ data = super().deferred_validate(data) try: filename = data["relative_path"] except KeyError: raise serializers.ValidationError( detail={"relative_path": _('This field is required')}) if python_models.PythonPackageContent.objects.filter( filename=filename): raise serializers.ValidationError( detail={"relative_path": _('This field must be unique')}) # iterate through extensions since splitext does not support things like .tar.gz for ext, packagetype in DIST_EXTENSIONS.items(): if filename.endswith(ext): # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it with tempfile.TemporaryDirectory() as td: temp_path = os.path.join(td, filename) artifact = data["artifact"] shutil.copy2(artifact.file.path, temp_path) metadata = DIST_TYPES[packagetype](temp_path) metadata.packagetype = packagetype break else: raise serializers.ValidationError( _("Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format( filename)) _data = parse_project_metadata(vars(metadata)) _data['packagetype'] = metadata.packagetype _data['version'] = metadata.version _data['filename'] = filename data.update(_data) new_content = python_models.PythonPackageContent.objects.filter( filename=data['filename'], packagetype=data['packagetype'], name=data['name'], version=data['version']) if new_content.exists(): raise serializers.ValidationError( _("There is already a python package with relative path '{path}'." ).format(path=data["relative_path"])) return data
def deferred_validate(self, data): """ Validate the python package data. Args: data (dict): Data to be validated Returns: dict: Data that has been validated """ data = super().deferred_validate(data) try: filename = data["relative_path"] except KeyError: raise serializers.ValidationError( detail={"relative_path": _('This field is required')}) # iterate through extensions since splitext does not support things like .tar.gz for ext, packagetype in DIST_EXTENSIONS.items(): if filename.endswith(ext): # Copy file to a temp directory under the user provided filename, we do this # because pkginfo validates that the filename has a valid extension before # reading it with tempfile.NamedTemporaryFile('wb', suffix=filename) as temp_file: artifact = data["artifact"] artifact_file = storage.open(artifact.file.name) shutil.copyfileobj(artifact_file, temp_file) temp_file.flush() metadata = DIST_TYPES[packagetype](temp_file.name) metadata.packagetype = packagetype break else: raise serializers.ValidationError( _("Extension on {} is not a valid python extension " "(.whl, .exe, .egg, .tar.gz, .tar.bz2, .zip)").format( filename)) if data.get("sha256") and data["sha256"] != artifact.sha256: raise serializers.ValidationError( detail={ "sha256": _("The uploaded artifact's sha256 checksum does not match the one provided" ) }) sha256 = artifact.sha256 if sha256 and python_models.PythonPackageContent.objects.filter( sha256=sha256).exists(): raise serializers.ValidationError( detail={"sha256": _('This field must be unique')}) _data = parse_project_metadata(vars(metadata)) _data['packagetype'] = metadata.packagetype _data['version'] = metadata.version _data['filename'] = filename _data['sha256'] = sha256 data.update(_data) return data