diff --git a/okonomiyaki/platforms/__init__.py b/okonomiyaki/platforms/__init__.py
index c4d0a73..bd7d12b 100644
--- a/okonomiyaki/platforms/__init__.py
+++ b/okonomiyaki/platforms/__init__.py
@@ -1,7 +1,7 @@
 # flake8: noqa
 from .abi import PlatformABI, default_abi
 from .epd_platform import X86, X86_64, EPDPlatform, applies
-from .platform import Platform
+from .platform import Platform, OSKind, FamilyKind, NameKind
 from .python_implementation import PythonABI, PythonImplementation
 
 __all__ = [
diff --git a/okonomiyaki/platforms/epd_platform.py b/okonomiyaki/platforms/epd_platform.py
index 503062b..97f4649 100644
--- a/okonomiyaki/platforms/epd_platform.py
+++ b/okonomiyaki/platforms/epd_platform.py
@@ -1,6 +1,7 @@
 from __future__ import absolute_import
 
 import re
+import warnings
 
 import six
 
@@ -128,7 +129,7 @@ class EPDPlatform(object):
         return _guess_epd_platform(arch)
 
     @classmethod
-    def from_epd_string(cls, s):
+    def from_string(cls, s):
         """
         Create a new instance from an epd platform string (e.g. 'win-32')
 
@@ -151,6 +152,19 @@ class EPDPlatform(object):
             platform = Platform(os, name, family, release, arch, machine)
             return cls(platform)
 
+    @classmethod
+    def from_epd_string(cls, s):
+        """
+        Create a new instance from an epd platform string (e.g. 'win-32')
+
+        DEPRECATED: use from_string instead.
+        """
+        warnings.warn(
+            "Deprecated: use EPDPlatform.from_string instead",
+            DeprecationWarning
+        )
+        return cls.from_string(s)
+
     @classmethod
     def _from_spec_depend_data(cls, platform, osdist, arch_name):
         msg = ("Unrecognized platform/osdist combination: {0!r}/{1!r}"

expose *Kind enum to `okonomiyaki.platforms`
diff --git a/okonomiyaki/platforms/tests/test_epd_platform.py b/okonomiyaki/platforms/tests/test_epd_platform.py
index a17ab89..ea9c5cb 100644
--- a/okonomiyaki/platforms/tests/test_epd_platform.py
+++ b/okonomiyaki/platforms/tests/test_epd_platform.py
@@ -41,24 +41,24 @@ class TestEPDPlatform(unittest.TestCase):
     def test_epd_platform_from_string(self):
         """Ensure every epd short platform is understood by EPDPlatform."""
         for epd_platform_string in EPD_PLATFORM_SHORT_NAMES:
-            EPDPlatform.from_epd_string(epd_platform_string)
+            EPDPlatform.from_string(epd_platform_string)
 
     def test_pep425_is_unicode(self):
         # When/Then
         for platform_string in self.platform_strings:
-            platform = EPDPlatform.from_epd_string(platform_string)
+            platform = EPDPlatform.from_string(platform_string)
             self.assertIsInstance(platform.pep425_tag, six.text_type)
 
     def test_platform_name(self):
         # When/Then
         for platform_string in self.platform_strings:
-            platform = EPDPlatform.from_epd_string(platform_string)
+            platform = EPDPlatform.from_string(platform_string)
             self.assertIsInstance(platform.platform_name, six.text_type)
 
     def test_str_is_unicode(self):
         # When/Then
         for platform_string in self.platform_strings:
-            platform = EPDPlatform.from_epd_string(platform_string)
+            platform = EPDPlatform.from_string(platform_string)
             self.assertIsInstance(six.text_type(platform), six.text_type)
 
     def test_epd_platform_from_string_new_names_underscore(self):
@@ -67,7 +67,7 @@ class TestEPDPlatform(unittest.TestCase):
 
         # When
         epd_platforms = tuple(
-            EPDPlatform.from_epd_string("rh5_" + arch)
+            EPDPlatform.from_string("rh5_" + arch)
             for arch in archs
         )
 
@@ -80,7 +80,7 @@ class TestEPDPlatform(unittest.TestCase):
 
         # When
         epd_platforms = tuple(
-            EPDPlatform.from_epd_string("rh5_" + arch)
+            EPDPlatform.from_string("rh5_" + arch)
             for arch in archs
         )
 
@@ -92,19 +92,19 @@ class TestEPDPlatform(unittest.TestCase):
         s = "win_x86_64"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(s)
+        epd_platform = EPDPlatform.from_string(s)
 
         # Then
-        self.assertEqual(epd_platform, EPDPlatform.from_epd_string("win-64"))
+        self.assertEqual(epd_platform, EPDPlatform.from_string("win-64"))
 
         # Given
         s = "osx_x86_64"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(s)
+        epd_platform = EPDPlatform.from_string(s)
 
         # Then
-        self.assertEqual(epd_platform, EPDPlatform.from_epd_string("osx-64"))
+        self.assertEqual(epd_platform, EPDPlatform.from_string("osx-64"))
 
     def test_epd_platform_from_string_new_names(self):
         """Ensure every epd short platform is understood by EPDPlatform."""
@@ -113,7 +113,7 @@ class TestEPDPlatform(unittest.TestCase):
 
         # When
         epd_platforms = tuple(
-            EPDPlatform.from_epd_string("rh5-" + arch)
+            EPDPlatform.from_string("rh5-" + arch)
             for arch in archs
         )
 
@@ -126,7 +126,7 @@ class TestEPDPlatform(unittest.TestCase):
 
         # When
         epd_platforms = tuple(
-            EPDPlatform.from_epd_string("rh5-" + arch)
+            EPDPlatform.from_string("rh5-" + arch)
             for arch in archs
         )
 
@@ -179,7 +179,7 @@ class TestEPDPlatform(unittest.TestCase):
         # When
         for old_name in EPD_PLATFORM_SHORT_NAMES:
             new_name = old_to_new_name(old_name)
-            name_to_platform[old_name] = EPDPlatform.from_epd_string(new_name)
+            name_to_platform[old_name] = EPDPlatform.from_string(new_name)
 
         # Then
         for old_name in name_to_platform:
@@ -195,13 +195,13 @@ class TestEPDPlatform(unittest.TestCase):
 
     def test_str(self):
         # Given
-        epd_platform = EPDPlatform.from_epd_string("rh5-64")
+        epd_platform = EPDPlatform.from_string("rh5-64")
 
         # When/Then
         self.assertEqual(str(epd_platform), "rh5_x86_64")
 
         # Given
-        epd_platform = EPDPlatform.from_epd_string("osx-32")
+        epd_platform = EPDPlatform.from_string("osx-32")
 
         # When/Then
         self.assertEqual(str(epd_platform), "osx_x86")
@@ -212,7 +212,7 @@ class TestEPDPlatform(unittest.TestCase):
         s = "osx_x86"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(s)
+        epd_platform = EPDPlatform.from_string(s)
 
         # Then
         self.assertEqual(str(epd_platform), s)
@@ -231,7 +231,7 @@ class TestEPDPlatform(unittest.TestCase):
         # When/Then
         for epd_string, platform_tag in epd_string_to_pep425:
             self.assertEqual(
-                EPDPlatform.from_epd_string(epd_string).pep425_tag,
+                EPDPlatform.from_string(epd_string).pep425_tag,
                 platform_tag,
             )
 
@@ -243,7 +243,7 @@ class TestEPDPlatformApplies(unittest.TestCase):
             self.assertTrue(applies("rh5", "current"))
             self.assertFalse(applies("!rh5", "current"))
 
-        platform = EPDPlatform.from_epd_string("rh5-x86_64")
+        platform = EPDPlatform.from_string("rh5-x86_64")
         self.assertTrue(applies("rh5", platform))
         self.assertFalse(applies("!rh5", platform))
         self.assertFalse(applies("rh5-32", platform))
@@ -254,7 +254,7 @@ class TestEPDPlatformApplies(unittest.TestCase):
             self.assertTrue(applies("all", "current"))
             self.assertFalse(applies("!all", "current"))
 
-        platform = EPDPlatform.from_epd_string("rh5-x86_64")
+        platform = EPDPlatform.from_string("rh5-x86_64")
         self.assertTrue(applies("all", platform))
         self.assertFalse(applies("!all", platform))
 
@@ -411,21 +411,21 @@ class TestGuessEPDPlatform(unittest.TestCase):
         # Given
         examples = (
             (("linux2", None, "x86"),
-             EPDPlatform.from_epd_string("rh5-32"),),
+             EPDPlatform.from_string("rh5-32"),),
             (("linux2", "RedHat_3", "x86"),
-             EPDPlatform.from_epd_string("rh3-32"),),
+             EPDPlatform.from_string("rh3-32"),),
             (("linux2", "RedHat_5", "x86"),
-             EPDPlatform.from_epd_string("rh5-32"),),
+             EPDPlatform.from_string("rh5-32"),),
             (("linux2", "RedHat_5", "amd64"),
-             EPDPlatform.from_epd_string("rh5-64"),),
+             EPDPlatform.from_string("rh5-64"),),
             (("darwin", None, "x86"),
-             EPDPlatform.from_epd_string("osx-32"),),
+             EPDPlatform.from_string("osx-32"),),
             (("darwin", None, "amd64"),
-             EPDPlatform.from_epd_string("osx-64"),),
+             EPDPlatform.from_string("osx-64"),),
             (("win32", None, "x86"),
-             EPDPlatform.from_epd_string("win-32"),),
+             EPDPlatform.from_string("win-32"),),
             (("win32", None, "amd64"),
-             EPDPlatform.from_epd_string("win-64"),),
+             EPDPlatform.from_string("win-64"),),
         )
 
         # When/Then
@@ -438,7 +438,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
         epd_platform_string = "rh5-32"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(epd_platform_string)
+        epd_platform = EPDPlatform.from_string(epd_platform_string)
 
         # Then
         platform = epd_platform.platform
@@ -452,7 +452,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
         epd_platform_string = "win-32"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(epd_platform_string)
+        epd_platform = EPDPlatform.from_string(epd_platform_string)
 
         # Then
         platform = epd_platform.platform
@@ -466,7 +466,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
         epd_platform_string = "osx-64"
 
         # When
-        epd_platform = EPDPlatform.from_epd_string(epd_platform_string)
+        epd_platform = EPDPlatform.from_string(epd_platform_string)
         platform = epd_platform.platform
 
         # Then
@@ -483,7 +483,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
 
         # When/Then
         with self.assertRaises(OkonomiyakiError):
-            EPDPlatform.from_epd_string(epd_platform_string)
+            EPDPlatform.from_string(epd_platform_string)
 
         # Given
         # Invalid bitwidth
@@ -491,7 +491,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
 
         # When/Then
         with self.assertRaises(OkonomiyakiError):
-            EPDPlatform.from_epd_string(epd_platform_string)
+            EPDPlatform.from_string(epd_platform_string)
 
         # Given
         # Invalid platform basename
@@ -499,7 +499,7 @@ class TestGuessEPDPlatform(unittest.TestCase):
 
         # When/Then
         with self.assertRaises(OkonomiyakiError):
-            EPDPlatform.from_epd_string(epd_platform_string)
+            EPDPlatform.from_string(epd_platform_string)
 
     def test_from_platform_tag(self):
         # Given

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
dev_requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==25.3.0
coverage==7.8.0
docutils==0.21.2
enum34==1.1.10
exceptiongroup==1.2.2
flake8==7.2.0
haas==0.9.0
iniconfig==2.1.0
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
mccabe==0.7.0
mock==1.0.1
-e git+https://github.com/enthought/okonomiyaki.git@5cbd87f7c349f999ac8d53fec18e44f5656bf5eb#egg=okonomiyaki
packaging==24.2
pbr==6.1.1
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.2
pytest==8.3.5
referencing==0.36.2
rpds-py==0.24.0
six==1.17.0
statistics==1.0.3.5
stevedore==4.1.1
testfixtures==8.3.0
tomli==2.2.1
typing_extensions==4.13.0
zipfile2==0.0.12

name: okonomiyaki
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==25.3.0
      - coverage==7.8.0
      - docutils==0.21.2
      - enum34==1.1.10
      - exceptiongroup==1.2.2
      - flake8==7.2.0
      - haas==0.9.0
      - iniconfig==2.1.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2024.10.1
      - mccabe==0.7.0
      - mock==1.0.1
      - packaging==24.2
      - pbr==6.1.1
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pytest==8.3.5
      - referencing==0.36.2
      - rpds-py==0.24.0
      - six==1.17.0
      - statistics==1.0.3.5
      - stevedore==4.1.1
      - testfixtures==8.3.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - zipfile2==0.0.12
prefix: /opt/conda/envs/okonomiyaki

okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_epd_platform_from_string okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_epd_platform_from_string_new_arch okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_epd_platform_from_string_new_names okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_epd_platform_from_string_new_names_underscore okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_pep425_is_unicode okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_pep425_tag okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_platform_name okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_str okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_str_is_unicode okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_from_epd_platform_string okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_from_epd_platform_string_invalid okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_from_spec_depend_data
okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_guessed_epd_platform okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatformApplies::test_all okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatformApplies::test_applies_rh okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatformApplies::test_current_linux okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatformApplies::test_no_arch okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_guess_linux2_platform okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_guess_linux2_unsupported
okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_from_running_python okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_from_running_system okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatform::test_short_names_consistency okonomiyaki/platforms/tests/test_epd_platform.py::TestEPDPlatformApplies::test_current_windows okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_from_platform_tag okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_guess_darwin_platform okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_guess_solaris_unsupported okonomiyaki/platforms/tests/test_epd_platform.py::TestGuessEPDPlatform::test_guess_win32_platform
okonomiyaki/platforms/__init__.py okonomiyaki/platforms/epd_platform.py
okonomiyaki/platforms/__init__.py okonomiyaki/platforms/epd_platform.py