openepd 0.1.3__py3-none-any.whl → 0.3.0__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.
openepd/__version__.py CHANGED
@@ -17,4 +17,4 @@
17
17
  # Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
18
18
  # Find out more at www.BuildingTransparency.org
19
19
  #
20
- VERSION = "0.1.3"
20
+ VERSION = "0.3.0"
openepd/model/base.py CHANGED
@@ -20,20 +20,47 @@
20
20
  import pydantic
21
21
  from pydantic.generics import GenericModel
22
22
 
23
+ AnySerializable = int | str | bool | float | list | dict | pydantic.BaseModel | None
24
+
23
25
 
24
26
  class BaseOpenEpdSchema(pydantic.BaseModel):
25
27
  """Base class for all OpenEPD models."""
26
28
 
29
+ ext: dict[str, AnySerializable] | None = pydantic.Field(alias="ext", default=None)
30
+
27
31
  class Config:
28
32
  allow_mutation = True
29
33
  validate_assignment = False
34
+ allow_population_by_field_name = True
35
+ use_enum_values = True
30
36
 
31
37
  def has_values(self) -> bool:
32
38
  """Return True if the model has any values."""
33
39
  return len(self.dict(exclude_unset=True, exclude_none=True)) > 0
34
40
 
41
+ @classmethod
42
+ def is_allowed_field_name(cls, field_name: str) -> bool:
43
+ """
44
+ Return True if the field name is defined in the module.
45
+
46
+ Both property name and aliases are checked.
47
+ """
48
+ if field_name in cls.__fields__:
49
+ return True
50
+ else:
51
+ for x in cls.__fields__.values():
52
+ if x.alias == field_name:
53
+ return True
54
+ return False
55
+
35
56
 
36
57
  class BaseOpenEpdGenericSchema(GenericModel, BaseOpenEpdSchema):
37
58
  """Base class for all OpenEPD generic models."""
38
59
 
39
60
  pass
61
+
62
+
63
+ class BaseOpenEpdSpec(BaseOpenEpdSchema):
64
+ """Base class for all OpenEPD specs."""
65
+
66
+ pass
openepd/model/common.py CHANGED
@@ -36,21 +36,10 @@ class Measurement(BaseOpenEpdSchema):
36
36
 
37
37
  mean: float = pyd.Field(description="Mean (expected) value of the measurement")
38
38
  unit: str = pyd.Field(description="Measurement unit")
39
- rsd: pyd.PositiveFloat = pyd.Field(description="Relative standard deviation, i.e. standard_deviation/mean")
40
- dist: str | None = pyd.Field(description="Statistical distribution of the measurement error.")
41
-
42
-
43
- class ExternalIdentification(BaseOpenEpdSchema): # TODO: NEW Object, not in the spec
44
- """Represent an external identification of an object."""
45
-
46
- id: str
47
- version: str | None
48
-
49
-
50
- class ExternallyIdentifiableMixin: # TODO: NEW Object, not in the spec
51
- """Mixin for objects that can be identified externally."""
52
-
53
- identified: dict[str, ExternalIdentification] = pyd.Field(description="The external identification of the object.")
39
+ rsd: pyd.PositiveFloat | None = pyd.Field(
40
+ description="Relative standard deviation, i.e. standard_deviation/mean", default=None
41
+ )
42
+ dist: str | None = pyd.Field(description="Statistical distribution of the measurement error.", default=None)
54
43
 
55
44
 
56
45
  class WithAttachmentsMixin:
openepd/model/epd.py CHANGED
@@ -23,12 +23,14 @@ from typing import Literal
23
23
  import pydantic as pyd
24
24
 
25
25
  from openepd.model.base import BaseOpenEpdSchema
26
- from openepd.model.common import Amount, ExternallyIdentifiableMixin
26
+ from openepd.model.common import Amount
27
27
  from openepd.model.lcia import ImpactSet, OutputFlowSet, ResourceUseSet
28
28
  from openepd.model.org import Org, Plant
29
+ from openepd.model.specs import Specs
30
+ from openepd.model.standard import Standard
29
31
 
30
32
 
31
- class Epd(ExternallyIdentifiableMixin, BaseOpenEpdSchema):
33
+ class Epd(BaseOpenEpdSchema):
32
34
  """Represent an EPD."""
33
35
 
34
36
  # TODO: Add validator for open-xpd-uuid on this field
@@ -120,3 +122,37 @@ class Epd(ExternallyIdentifiableMixin, BaseOpenEpdSchema):
120
122
  description="Set of Waste and Output Flow indicators which describe the waste categories "
121
123
  "and other material output flows derived from the LCI."
122
124
  )
125
+ compliance: list[Standard] = pyd.Field(
126
+ description="Standard(s) to which this declaration is compliant.", default_factory=list
127
+ )
128
+ specs: Specs = pyd.Field(
129
+ default_factory=Specs,
130
+ description="Data structure(s) describing performance specs of product. Unique for each material type.",
131
+ )
132
+ lca_discussion: str | None = pyd.Field(
133
+ max_length=20000,
134
+ description="""A rich text description containing information for experts reviewing the EPD contents.
135
+ Text descriptions required by ISO 14025, ISO 21930, EN 15804,, relevant PCRs, or program instructions and which do not
136
+ have specific openEPD fields should be entered here. This field may be large, and may contain multiple sections
137
+ separated by github flavored markdown formatting.""",
138
+ example="""# Packaging
139
+
140
+ Information on product-specific packaging: type, composition and possible reuse of packaging materials (paper,
141
+ strapping, pallets, foils, drums, etc.) shall be included in this Section. The EPD shall describe specific packaging
142
+ scenario assumptions, including disposition pathways for each packaging material by reuse, recycling, or landfill
143
+ disposal based on packaging type.*
144
+
145
+ # Product Installation
146
+
147
+ A description of the type of processing, machinery, tools, dust extraction equipment, auxiliary materials, etc.
148
+ to be used during installation shall be included. Information on industrial and environmental protection may be
149
+ included in this section. Any waste treatment included within the system boundary of installation waste should be
150
+ specified.
151
+
152
+ # Use Conditions
153
+
154
+ Use-stage environmental impacts of flooring products during building operations depend on product cleaning assumptions.
155
+ Information on cleaning frequency and cleaning products shall be provided based on the manufacturer’s recommendations.
156
+ In the absence of primary data, cleaning assumptions shall be documented.
157
+ """,
158
+ )
openepd/model/org.py CHANGED
@@ -22,7 +22,7 @@ from typing import Annotated, Optional
22
22
  import pydantic as pyd
23
23
 
24
24
  from openepd.model.base import BaseOpenEpdSchema
25
- from openepd.model.common import ExternallyIdentifiableMixin, WithAttachmentsMixin
25
+ from openepd.model.common import WithAttachmentsMixin
26
26
 
27
27
 
28
28
  class Contact(BaseOpenEpdSchema): # TODO: NEW Object, not in the spec
@@ -35,9 +35,7 @@ class Contact(BaseOpenEpdSchema): # TODO: NEW Object, not in the spec
35
35
  )
36
36
 
37
37
 
38
- class Org(
39
- ExternallyIdentifiableMixin, WithAttachmentsMixin, BaseOpenEpdSchema
40
- ): # TODO: NEW Identifiable field, not in the spec
38
+ class Org(WithAttachmentsMixin, BaseOpenEpdSchema): # TODO: NEW Identifiable field, not in the spec
41
39
  """Represent an organization."""
42
40
 
43
41
  web_domain: str = pyd.Field(
@@ -59,7 +57,7 @@ class Org(
59
57
  )
60
58
 
61
59
 
62
- class Plant(ExternallyIdentifiableMixin, WithAttachmentsMixin, BaseOpenEpdSchema):
60
+ class Plant(WithAttachmentsMixin, BaseOpenEpdSchema):
63
61
  """Represent a manufacturing plant."""
64
62
 
65
63
  # TODO: Add proper validator
openepd/model/pcr.py CHANGED
@@ -23,11 +23,11 @@ from typing import Optional
23
23
  import pydantic as pyd
24
24
 
25
25
  from openepd.model.base import BaseOpenEpdSchema
26
- from openepd.model.common import ExternallyIdentifiableMixin, WithAttachmentsMixin
26
+ from openepd.model.common import WithAttachmentsMixin
27
27
  from openepd.model.org import Org
28
28
 
29
29
 
30
- class Pcr(ExternallyIdentifiableMixin, WithAttachmentsMixin, BaseOpenEpdSchema):
30
+ class Pcr(WithAttachmentsMixin, BaseOpenEpdSchema):
31
31
  """Represent a PCR (Product Category Rules)."""
32
32
 
33
33
  id: str = pyd.Field(
@@ -0,0 +1,29 @@
1
+ #
2
+ # Copyright 2023 by C Change Labs Inc. www.c-change-labs.com
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # This software was developed with support from the Skanska USA,
17
+ # Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
18
+ # Find out more at www.BuildingTransparency.org
19
+ #
20
+ import pydantic as pyd
21
+
22
+ from openepd.model.base import BaseOpenEpdSchema
23
+ from openepd.model.specs.concrete import CmuSpec
24
+
25
+
26
+ class Specs(BaseOpenEpdSchema):
27
+ """Material specific specs."""
28
+
29
+ cmu: CmuSpec | None = pyd.Field(default=None, description="Concrete Masonry Unit-specific (CMU) specs")
@@ -0,0 +1,83 @@
1
+ #
2
+ # Copyright 2023 by C Change Labs Inc. www.c-change-labs.com
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # This software was developed with support from the Skanska USA,
17
+ # Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
18
+ # Find out more at www.BuildingTransparency.org
19
+ #
20
+ from enum import StrEnum
21
+
22
+ import pydantic as pyd
23
+
24
+ from openepd.model.base import BaseOpenEpdSpec
25
+
26
+
27
+ class CmuWeightClassification(StrEnum):
28
+ """Concrete Masonry Unit weight classification."""
29
+
30
+ Normal = "Normal"
31
+ """Normal weight CMU has a density of 125 lbs/cu. ft."""
32
+ Medium = "Medium"
33
+ """Medium weight CMU has a density of 105-125 lbs/cu. ft."""
34
+ Light = "Light"
35
+ """Lightweight CMU has a density less than 105 lbs/cu. ft."""
36
+
37
+
38
+ class CmuOptions(BaseOpenEpdSpec):
39
+ """Concrete Masonry Unit options."""
40
+
41
+ load_bearing: bool | None = pyd.Field(
42
+ description="Load-Bearing. CMUs intended to be loadbearing, rather than simply cosmetic",
43
+ example=True,
44
+ default=None,
45
+ )
46
+ aerated_concrete: bool | None = pyd.Field(
47
+ description="AAC Aerated Concrete. Aerated Autoclaved Concrete, a foam concrete.", example=True, default=None
48
+ )
49
+ insulated: bool | None = pyd.Field(
50
+ description="Insulated. CMUs with integral insulation", example=True, default=None
51
+ )
52
+ sound_absorbing: bool | None = pyd.Field(
53
+ description="Sound Absorbing. CMUs structured for sound absorbtion", example=True, default=None
54
+ )
55
+ white: bool | None = pyd.Field(
56
+ description="White. CMU using white cement and light-colored aggregate", example=True, default=None
57
+ )
58
+ recycled_aggregate: bool | None = pyd.Field(
59
+ description="Recycled aggregate. CMU using primarily reycled aggregates", example=True, default=None
60
+ )
61
+ groundface: bool | None = pyd.Field(
62
+ description="Ground Face. Ground or Honed facing, typically for improved appearance", example=True, default=None
63
+ )
64
+ splitface: bool | None = pyd.Field(
65
+ description="Splitface. Rough surface texture via splitting; aggregate can be seen", example=True, default=None
66
+ )
67
+ smoothface: bool | None = pyd.Field(
68
+ description="Smooth Face. Standard smooth-faced blocks", example=True, default=None
69
+ )
70
+ slumpstone: bool | None = pyd.Field(
71
+ description="Slumpstone. A slightly rounded, random distortion with the look of rustic adobe.",
72
+ example=True,
73
+ default=None,
74
+ )
75
+
76
+
77
+ class CmuSpec(BaseOpenEpdSpec):
78
+ """Standardized Concrete Masonry Unit-specific extension for OpenEPD."""
79
+
80
+ strength: str = pyd.Field(description="Compressive strength", example="4000 psi")
81
+ options: CmuOptions = pyd.Field(
82
+ description="Options for CMU. List of true/false properties", default_factory=CmuOptions
83
+ )
@@ -0,0 +1,34 @@
1
+ #
2
+ # Copyright 2023 by C Change Labs Inc. www.c-change-labs.com
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # This software was developed with support from the Skanska USA,
17
+ # Charles Pankow Foundation, Microsoft Sustainability Fund, Interface, MKA Foundation, and others.
18
+ # Find out more at www.BuildingTransparency.org
19
+ #
20
+ import pydantic as pyd
21
+
22
+ from openepd.model.base import BaseOpenEpdSchema
23
+ from openepd.model.org import Org
24
+
25
+
26
+ class Standard(BaseOpenEpdSchema):
27
+ """A standard, such as EN 15804, ISO 14044, ISO 14024:2018, etc."""
28
+
29
+ short_name: str = pyd.Field(description="Short-form of name of standard. Must be unique. Case-insensitive")
30
+ name: str | None = pyd.Field(description="Full document name. Must be unique. Case-insensitive", default=None)
31
+ link: pyd.AnyUrl | None = pyd.Field(
32
+ description="Link to the exact standard (including version) referred to", default=None
33
+ )
34
+ issuer: Org | None = pyd.Field(description="Org that issued this standard", default=None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openepd
3
- Version: 0.1.3
3
+ Version: 0.3.0
4
4
  Summary: Python library to work with OpenEPD format
5
5
  Home-page: https://github.com/cchangelabs/openepd
6
6
  License: Apache-2.0
@@ -0,0 +1,17 @@
1
+ openepd/__init__.py,sha256=7_QNx3x9RCC7Lj9fHDD3nzgq6wV4Fmou7OJNWkCPnEw,837
2
+ openepd/__version__.py,sha256=M9l7ZzgmpFsB59avClU0_PB_PUhypOp28sEbL1pAGQU,855
3
+ openepd/model/__init__.py,sha256=7_QNx3x9RCC7Lj9fHDD3nzgq6wV4Fmou7OJNWkCPnEw,837
4
+ openepd/model/base.py,sha256=Dpc8YeGf70gHahGrLbCC2e4MFCI6BHoByNSGdN3Ul7c,2155
5
+ openepd/model/common.py,sha256=DomuW6IRVyOpbo-wJbrPpWa7ig65OzAncSzA63Imyy8,2178
6
+ openepd/model/epd.py,sha256=_BZoLHOz8uDL0lDqHAYgPxOiJ39hHfWCbVAdXqIhWWk,7763
7
+ openepd/model/lcia.py,sha256=N_2TukAXKCz5ztWHRdOrw2UVmAhLn9WN9x9y6_BJ6Uw,8887
8
+ openepd/model/org.py,sha256=kQyaCi6pRzaThJ_13o4ymEfNoSBXXZP0wVoZA7mse6o,3690
9
+ openepd/model/pcr.py,sha256=RmOB9YLkNJIU1RAvHSDzOOIL3ux3FmJo60oCkXXu_08,2855
10
+ openepd/model/specs/__init__.py,sha256=JmbvfzwO0QmNcrxGqYE_KjvYHBmc2bnDm7cyZsaMG78,1137
11
+ openepd/model/specs/concrete.py,sha256=v9Jyi6NiaoMA2ELX_wMckgTAtRplEOaIkZrd2qEdiN4,3342
12
+ openepd/model/standard.py,sha256=Nv_H3Lhu79y4waWzzKpwODCPPGrlWwRIl6eZBMSc9Qg,1519
13
+ openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ openepd-0.3.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
15
+ openepd-0.3.0.dist-info/METADATA,sha256=ASVre0j0f1CKolSXk10wzB6FmSros-KnUoiw3IbVvuM,3723
16
+ openepd-0.3.0.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
17
+ openepd-0.3.0.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- openepd/__init__.py,sha256=7_QNx3x9RCC7Lj9fHDD3nzgq6wV4Fmou7OJNWkCPnEw,837
2
- openepd/__version__.py,sha256=T87cqTOIorCpfwNyvo0jvQ5LS27mv02hQMmtN92zYkU,855
3
- openepd/model/__init__.py,sha256=7_QNx3x9RCC7Lj9fHDD3nzgq6wV4Fmou7OJNWkCPnEw,837
4
- openepd/model/base.py,sha256=2kaIyTze9V0ItX-yNFFHGRIF3ewDuoF_GGbYbfAT_iI,1366
5
- openepd/model/common.py,sha256=_Vn2ysWrJFYHZKBe8cxnPhV45RR3KzIPjfKXLPJOTVA,2573
6
- openepd/model/epd.py,sha256=5KvTvG3uX5hhVyp9iuDhjz_8fgVV8IC4wextNToVoiU,5740
7
- openepd/model/lcia.py,sha256=N_2TukAXKCz5ztWHRdOrw2UVmAhLn9WN9x9y6_BJ6Uw,8887
8
- openepd/model/org.py,sha256=k3fpFwVPnN80UIJJFu-kPUCIyD2iIavtDeTCKwGTFIg,3783
9
- openepd/model/pcr.py,sha256=vEwd2V6IFau1vXC8MC8Ptx6YXySrFgOuiho_J1ZxhJg,2913
10
- openepd/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- openepd-0.1.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
- openepd-0.1.3.dist-info/METADATA,sha256=H_SXczzF5ijpPxydL3XQ5FGEVuLAWVfkNcz5onAu4ig,3723
13
- openepd-0.1.3.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
14
- openepd-0.1.3.dist-info/RECORD,,