diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go
index 66380d832c..4c8041c30c 100644
--- a/routers/api/packages/pypi/pypi.go
+++ b/routers/api/packages/pypi/pypi.go
@@ -21,9 +21,9 @@ import (
 	packages_service "code.gitea.io/gitea/services/packages"
 )
 
-// https://www.python.org/dev/peps/pep-0503/#normalized-names
+// https://peps.python.org/pep-0426/#name
 var normalizer = strings.NewReplacer(".", "-", "_", "-")
-var nameMatcher = regexp.MustCompile(`\A[a-zA-Z0-9\.\-_]+\z`)
+var nameMatcher = regexp.MustCompile(`\A(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\.\-_]*[a-zA-Z0-9])\z`)
 
 // https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
 var versionMatcher = regexp.MustCompile(`\Av?` +
@@ -128,7 +128,7 @@ func UploadPackageFile(ctx *context.Context) {
 
 	packageName := normalizer.Replace(ctx.Req.FormValue("name"))
 	packageVersion := ctx.Req.FormValue("version")
-	if !nameMatcher.MatchString(packageName) || !versionMatcher.MatchString(packageVersion) {
+	if !isValidNameAndVersion(packageName, packageVersion) {
 		apiError(ctx, http.StatusBadRequest, "invalid name or version")
 		return
 	}
@@ -146,7 +146,7 @@ func UploadPackageFile(ctx *context.Context) {
 				Name:        packageName,
 				Version:     packageVersion,
 			},
-			SemverCompatible: true,
+			SemverCompatible: false,
 			Creator:          ctx.Doer,
 			Metadata: &pypi_module.Metadata{
 				Author:          ctx.Req.FormValue("author"),
@@ -177,3 +177,7 @@ func UploadPackageFile(ctx *context.Context) {
 
 	ctx.Status(http.StatusCreated)
 }
+
+func isValidNameAndVersion(packageName, packageVersion string) bool {
+	return nameMatcher.MatchString(packageName) && versionMatcher.MatchString(packageVersion)
+}
diff --git a/routers/api/packages/pypi/pypi_test.go b/routers/api/packages/pypi/pypi_test.go
new file mode 100644
index 0000000000..56e327a347
--- /dev/null
+++ b/routers/api/packages/pypi/pypi_test.go
@@ -0,0 +1,39 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package pypi
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestIsValidNameAndVersion(t *testing.T) {
+	// The test cases below were created from the following Python PEPs:
+	// https://peps.python.org/pep-0426/#name
+	// https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
+
+	// Valid Cases
+	assert.True(t, isValidNameAndVersion("A", "1.0.1"))
+	assert.True(t, isValidNameAndVersion("Test.Name.1234", "1.0.1"))
+	assert.True(t, isValidNameAndVersion("test_name", "1.0.1"))
+	assert.True(t, isValidNameAndVersion("test-name", "1.0.1"))
+	assert.True(t, isValidNameAndVersion("test-name", "v1.0.1"))
+	assert.True(t, isValidNameAndVersion("test-name", "2012.4"))
+	assert.True(t, isValidNameAndVersion("test-name", "1.0.1-alpha"))
+	assert.True(t, isValidNameAndVersion("test-name", "1.0.1a1"))
+	assert.True(t, isValidNameAndVersion("test-name", "1.0b2.r345.dev456"))
+	assert.True(t, isValidNameAndVersion("test-name", "1!1.0.1"))
+	assert.True(t, isValidNameAndVersion("test-name", "1.0.1+local.1"))
+
+	// Invalid Cases
+	assert.False(t, isValidNameAndVersion(".test-name", "1.0.1"))
+	assert.False(t, isValidNameAndVersion("test!name", "1.0.1"))
+	assert.False(t, isValidNameAndVersion("-test-name", "1.0.1"))
+	assert.False(t, isValidNameAndVersion("test-name-", "1.0.1"))
+	assert.False(t, isValidNameAndVersion("test-name", "a1.0.1"))
+	assert.False(t, isValidNameAndVersion("test-name", "1.0.1aa"))
+	assert.False(t, isValidNameAndVersion("test-name", "1.0.0-alpha.beta"))
+}
diff --git a/tests/integration/api_packages_pypi_test.go b/tests/integration/api_packages_pypi_test.go
index 0cd6ff7d13..83719dcca0 100644
--- a/tests/integration/api_packages_pypi_test.go
+++ b/tests/integration/api_packages_pypi_test.go
@@ -29,7 +29,7 @@ func TestPackagePyPI(t *testing.T) {
 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
 
 	packageName := "test-package"
-	packageVersion := "1.0.1+r1234"
+	packageVersion := "1!1.0.1+r1234"
 	packageAuthor := "KN4CK3R"
 	packageDescription := "Test Description"
 
@@ -72,7 +72,7 @@ func TestPackagePyPI(t *testing.T) {
 
 		pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
 		assert.NoError(t, err)
-		assert.NotNil(t, pd.SemVer)
+		assert.Nil(t, pd.SemVer)
 		assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
 		assert.Equal(t, packageName, pd.Package.Name)
 		assert.Equal(t, packageVersion, pd.Version.Version)
@@ -100,7 +100,7 @@ func TestPackagePyPI(t *testing.T) {
 
 		pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
 		assert.NoError(t, err)
-		assert.NotNil(t, pd.SemVer)
+		assert.Nil(t, pd.SemVer)
 		assert.IsType(t, &pypi.Metadata{}, pd.Metadata)
 		assert.Equal(t, packageName, pd.Package.Name)
 		assert.Equal(t, packageVersion, pd.Version.Version)